Skip to content

Implement OAuth2 security test coverage#862

Merged
rapids-bot[bot] merged 6 commits intoNVIDIA:developfrom
ericevans-nv:oauth-security-test-suite
Sep 29, 2025
Merged

Implement OAuth2 security test coverage#862
rapids-bot[bot] merged 6 commits intoNVIDIA:developfrom
ericevans-nv:oauth-security-test-suite

Conversation

@ericevans-nv
Copy link
Contributor

@ericevans-nv ericevans-nv commented Sep 27, 2025

Description

This PR adds comprehensive security testing for OAuth2 authorization code flows and enhances token validation coverage. The implementation includes parameterized tests for redirect URI validation, authorization code security (one-time use, expiration, client binding), and state parameter handling to prevent CSRF attacks. Additionally, it extends bearer token validation with expiration testing for both JWT and opaque tokens, and implements authentication log suppression to prevent sensitive credential leakage. The test suite covers critical OAuth2 security requirements including PKCE validation, error response handling, and proper authentication flow component integration across both console and WebSocket handlers.

By Submitting this PR I confirm:

  • I am familiar with the Contributing Guidelines.
  • We require that all contributors "sign-off" on their commits. This certifies that the contribution is your original work, or you have rights to submit it under the same license, or a compatible license.
    • Any contribution which contains commits that are not Signed-Off will not be accepted.
  • When the PR is ready for review, new or existing tests cover these changes.
  • When the PR is ready for review, the documentation is up to date with these changes.

Summary by CodeRabbit

  • Bug Fixes

    • Improved OAuth2 error handling: distinct messages for authorization, network, and timeout failures; token refresh now fails gracefully; browser-launch and redirect errors surface clearer user-facing messages.
  • Refactor

    • Centralized authorization URL and redirect handling via internal helpers; in-process redirect app exposure improved while public interfaces remain unchanged.
  • Documentation

    • Clarified docstrings around local redirect server vs test-mode behavior.
  • Tests

    • Added extensive end-to-end OAuth2 security tests, expiry/scope checks, and error-recovery tests; adjusted async test markers.
  • Chores

    • Added logging and HTTP client dependency for better error reporting.

Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
@ericevans-nv ericevans-nv requested a review from a team as a code owner September 27, 2025 01:05
@coderabbitai
Copy link

coderabbitai bot commented Sep 27, 2025

Walkthrough

Refines OAuth2 error handling across console, FastAPI (websocket & plugin) handlers and the token refresh provider; adds helper for building authorization URLs with PKCE, exposes an in-process redirect app field, and introduces extensive OAuth security and expiry tests.

Changes

Cohort / File(s) Summary
OAuth2 token refresh handling
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
Adds module logger and httpx import; wraps _attempt_token_refresh call in try/except, explicitly handles httpx.HTTPStatusError and httpx.RequestError, returns None on these or other exceptions.
Console flow handler
src/nat/front_ends/console/authentication_flow_handler.py
Adds private `_redirect_app: FastAPI
FastAPI WebSocket flow handler
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
Adds OAuthError alias import and _create_authorization_url helper; tightens error handling in create_oauth_client (maps ValueError/TypeError/OAuthError/Exception to RuntimeError); replaces inline URL creation with helper; renames cfgconfig parameter usage.
FastAPI plugin redirect handler
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
Adds httpx and OAuthError handling in the redirect handler: maps OAuthError, httpx.HTTPError, and other exceptions to RuntimeError set on the flow future; success response now includes explicit headers.
Bearer token validator tests
tests/nat/authentication/test_bearer_token_validator.py
Removes several pytest.mark.asyncio decorators; adds tests: test_jwt_insufficient_scopes_rejected, test_jwt_expired_token_rejected, test_opaque_expired_token_rejected.
Console flow tests
tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
Adds test_console_oauth2_flow_error_handling that injects a failing OAuth client constructor raising ValueError and asserts the original error is propagated; patches browser/CLI echo in test.
OAuth security tests (new module)
tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
New comprehensive test module exercising redirect URI validation, state/scopes handling, error scenarios, authorization-code security, and log-filtering via a MockOAuth2Server and ASGI/httpx interactions.
WebSocket flow tests
tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py
Renames cfgconfig; adds test_websocket_oauth2_flow_error_handling asserting a RuntimeError (timeout-related message) when OAuth client creation fails.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Console as ConsoleAuthFlow
  participant Browser
  participant OAuth as AuthServer
  participant Redirect as RedirectApp

  Note over Console: start authenticate()
  Console->>Console: create_oauth_client()
  alt client creation fails
    Console-->>User: raise/propagate error
  else
    Console->>Console: _create_authorization_url(state, PKCE?)
    alt url creation fails
      Console-->>User: RuntimeError
    else
      Console->>Browser: open(auth URL) (guarded)
      Browser->>OAuth: authorize
      OAuth-->>Redirect: redirect with code/state
      Redirect->>Redirect: exchange code -> token
      alt OAuthError
        Redirect-->>Console: set flow future exception (RuntimeError OAuth)
      else httpx.HTTPError
        Redirect-->>Console: set flow future exception (RuntimeError network)
      else other error
        Redirect-->>Console: set flow future exception (RuntimeError)
      else success
        Redirect-->>Console: set flow future result (tokens)
      end
      Console-->>User: return result or error
    end
  end
Loading
sequenceDiagram
  autonumber
  participant WSClient as WS Client
  participant WSFlow as WebSocketFlowHandler
  participant OAuth as AuthServer
  participant Redirect as PluginRedirect

  WSClient->>WSFlow: initiate flow
  WSFlow->>WSFlow: create_oauth_client()
  alt invalid config / error
    WSFlow-->>WSClient: RuntimeError (wrapped)
  else
    WSFlow->>WSFlow: _create_authorization_url()
    alt failure
      WSFlow-->>WSClient: RuntimeError
    else
      WSFlow->>OAuth: authorize
      OAuth-->>Redirect: callback -> code/state
      Redirect->>Redirect: token exchange
      alt OAuthError / httpx / other
        Redirect-->>WSFlow: set exception (RuntimeError)
      else success
        Redirect-->>WSFlow: set result (tokens)
      end
      WSFlow-->>WSClient: result or error (timeout preserved)
    end
  end
Loading
sequenceDiagram
  autonumber
  participant Provider as OAuth2AuthCodeFlowProvider
  participant TokenAS as TokenEndpoint

  Note over Provider: _attempt_token_refresh()
  Provider->>TokenAS: POST /token (refresh_token)
  alt httpx.HTTPStatusError or httpx.RequestError
    Provider-->>Provider: return None
  else other Exception
    Provider-->>Provider: return None
  else success
    Provider-->>Provider: return refreshed token
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

improvement, tests, security

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “Implement OAuth2 security test coverage” uses an imperative verb, succinctly describes the main change of adding comprehensive OAuth2 security tests, and is clearly related to the pull request’s objective of expanding test coverage for OAuth2 flows without exceeding recommended length.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ericevans-nv ericevans-nv self-assigned this Sep 27, 2025
@ericevans-nv ericevans-nv added feature request New feature or request non-breaking Non-breaking change labels Sep 27, 2025
@coderabbitai coderabbitai bot added external This issue was filed by someone outside of the NeMo Agent toolkit team improvement Improvement to existing functionality labels Sep 27, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py (1)

164-199: Console error test asserts the wrong exception type

ConsoleAuthenticationFlowHandler.construct_oauth_client now wraps OAuthError/ValueError/TypeError and re-raises a RuntimeError (see src/nat/front_ends/console/authentication_flow_handler.py, Line 90-109). This test instead hardcodes a ValueError expectation, effectively locking in the inconsistent behavior we just removed. If we exercise the real implementation (without the override), the test will fail because the handler correctly surfaces a RuntimeError. Please update the test to drive the production path (patch the AsyncOAuth2Client constructor to raise) and assert the wrapped RuntimeError message.

Apply this diff to align the test with the production behavior:

-async def test_console_oauth2_flow_error_handling(monkeypatch, mock_server):
-    """Test that Console flow does NOT convert OAuth client creation errors to RuntimeError (inconsistent behavior)."""
-
-    # Create a handler that will fail during OAuth client construction
-    class _FailingTestHandler(ConsoleAuthenticationFlowHandler):
-
-        def __init__(self):
-            super().__init__()
-
-        def construct_oauth_client(self, cfg):
-            # Force a failure during OAuth client creation
-            raise ValueError("Invalid OAuth client configuration")
-
-    cfg = OAuth2AuthCodeFlowProviderConfig(
+async def test_console_oauth2_flow_error_handling(monkeypatch):
+    """Console flow should surface OAuth client construction failures as RuntimeError (matches other front-ends)."""
+
+    cfg = OAuth2AuthCodeFlowProviderConfig(
         client_id="test_client",
         client_secret="test_secret",
         authorization_url="http://testserver/oauth/authorize",
         token_url="http://testserver/oauth/token",
         scopes=["read"],
         use_pkce=True,
         redirect_uri="http://localhost:8000/auth/redirect",
     )
 
-    handler = _FailingTestHandler()
+    handler = ConsoleAuthenticationFlowHandler()
+
+    class _ExplodingAsyncOAuth2Client:  # pragma: no cover - simple test double
+
+        def __init__(self, *args, **kwargs):
+            raise ValueError("Invalid OAuth client configuration")
 
     monkeypatch.setattr("webbrowser.open", lambda *_: None, raising=True)  # Don't actually open browser
     monkeypatch.setattr("click.echo", lambda *_: None, raising=True)  # silence CLI
+    monkeypatch.setattr(
+        "nat.front_ends.console.authentication_flow_handler.AsyncOAuth2Client",
+        _ExplodingAsyncOAuth2Client,
+        raising=True,
+    )
 
-    # Assert that ValueError is raised (NOT converted to RuntimeError - demonstrates inconsistent error handling)
-    with pytest.raises(ValueError) as exc_info:
+    # Assert that the handler now raises RuntimeError with the wrapped message.
+    with pytest.raises(RuntimeError) as exc_info:
         await handler.authenticate(cfg, AuthFlowType.OAUTH2_AUTHORIZATION_CODE)
 
     # Verify the error message contains the original exception information
     error_message = str(exc_info.value)
-    assert "Invalid OAuth client configuration" in error_message
+    assert "Invalid OAuth2 configuration" in error_message
tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py (1)

181-223: WebSocket error test currently stalls for 5 minutes

WebSocketAuthenticationFlowHandler._handle_oauth2_auth_code_flow waits on asyncio.wait_for(..., timeout=300). In this test no token ever arrives, so we literally sleep five minutes before asyncio.TimeoutError fires. Besides blowing up suite runtime, it still doesn’t exercise the intended error path (OAuth client construction wrapping). Please force the constructor to fail and assert the wrapped RuntimeError immediately, just like the console test.

Apply this diff to avoid the 5-minute stall and verify the real failure mode:

-@pytest.mark.usefixtures("set_nat_config_file_env_var")
-async def test_websocket_oauth2_flow_error_handling(monkeypatch, mock_server, tmp_path):
-    """Test that WebSocket flow does convert OAuth client creation errors to RuntimeError (consistent behavior)."""
+@pytest.mark.usefixtures("set_nat_config_file_env_var")
+async def test_websocket_oauth2_flow_error_handling(monkeypatch, tmp_path):
+    """WebSocket flow should surface OAuth client construction failures as RuntimeError (consistent with console)."""
 
     cfg_nat = Config(workflow=EchoFunctionConfig())
     worker = FastApiFrontEndPluginWorker(cfg_nat)
 
     # Dummy WebSocket handler
     class _DummyWSHandler:
@@
-    # Use a config that will pass pydantic validation but fail OAuth client creation
     cfg_flow = OAuth2AuthCodeFlowProviderConfig(
         client_id="",  # Empty string passes pydantic but may cause OAuth client errors
         client_secret="",  # Empty strings should trigger error handling
         authorization_url="http://testserver/oauth/authorize",
         token_url="http://testserver/oauth/token",
         scopes=["read"],
         use_pkce=True,
         redirect_uri="http://localhost:8000/auth/redirect",
     )
 
     monkeypatch.setattr("click.echo", lambda *_: None, raising=True)
 
-    # This test demonstrates the WebSocket flow does have timeout protection (RuntimeError after 5 minutes)
-    # but the OAuth client creation with empty strings doesn't actually fail as expected
+    class _ExplodingAsyncOAuth2Client:
+
+        def __init__(self, *args, **kwargs):
+            raise ValueError("Invalid OAuth client configuration")
+
+    monkeypatch.setattr(
+        "nat.front_ends.fastapi.auth_flow_handlers.websocket_flow_handler.AsyncOAuth2Client",
+        _ExplodingAsyncOAuth2Client,
+        raising=True,
+    )
+
     with pytest.raises(RuntimeError) as exc_info:
         await ws_handler.authenticate(cfg_flow, AuthFlowType.OAUTH2_AUTHORIZATION_CODE)
 
-    # Verify timeout RuntimeError is raised (demonstrates partial error handling)
     error_message = str(exc_info.value)
-    assert "Authentication flow timed out" in error_message
+    assert "Invalid OAuth2 configuration" in error_message
🧹 Nitpick comments (3)
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (1)

62-69: Log refresh failures instead of swallowing them silently.

Every branch in the try block returns None, but nothing gets logged. When refreshes start failing in production we will have zero signal, which makes diagnosing auth regressions painful. Please emit a warning (with context like user_id) before returning so we have breadcrumbs in the logs.

         try:
             with AuthlibOAuth2Client(
                     client_id=self.config.client_id,
                     client_secret=self.config.client_secret,
             ) as client:
                 new_token_data = client.refresh_token(self.config.token_url, refresh_token=refresh_token)
@@
-        except httpx.HTTPStatusError:
-            return None
-        except httpx.RequestError:
-            return None
-        except Exception:
-            # On any other failure, we'll fall back to the full auth flow.
-            return None
+        except httpx.HTTPStatusError:
+            logger.warning("HTTP %s while refreshing token for user %s; falling back to full auth flow.",
+                           "HTTPStatusError", user_id)
+            return None
+        except httpx.RequestError as exc:
+            logger.warning("Network error while refreshing token for user %s: %s", user_id, exc)
+            return None
+        except Exception as exc:
+            # On any other failure, we'll fall back to the full auth flow.
+            logger.exception("Unexpected error while refreshing token for user %s", user_id)
+            return None
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (1)

1078-1083: Surface redirect failures in logs before returning success HTML.

We now map OAuth/httpx/other exceptions into RuntimeErrors on the flow future, but we never log the underlying reason. When redirects fail we will still render the success HTML and silently drop the stack trace, which makes production debugging very hard. Please log each branch (OAuth, network, generic) before setting the exception so operators can correlate failures.

-            except OAuthError as e:
-                flow_state.future.set_exception(
-                    RuntimeError(f"Authorization server rejected request: {e.error} ({e.description})"))
-            except httpx.HTTPError as e:
-                flow_state.future.set_exception(RuntimeError(f"Network error during token fetch: {e}"))
-            except Exception as e:
-                flow_state.future.set_exception(RuntimeError(f"Authentication failed: {e}"))
+            except OAuthError as e:
+                logger.warning("OAuth error during token fetch for state %s: %s (%s)", state, e.error, e.description)
+                flow_state.future.set_exception(
+                    RuntimeError(f"Authorization server rejected request: {e.error} ({e.description})"))
+            except httpx.HTTPError as e:
+                logger.warning("Network error during token fetch for state %s: %s", state, e)
+                flow_state.future.set_exception(RuntimeError(f"Network error during token fetch: {e}"))
+            except Exception as e:
+                logger.exception("Unexpected authentication failure during token fetch for state %s", state)
+                flow_state.future.set_exception(RuntimeError(f"Authentication failed: {e}"))
src/nat/front_ends/console/authentication_flow_handler.py (1)

116-117: Use explicit union types for optional parameters

Per our typing guidelines and Ruff’s RUF013 hint, please spell optional parameters with explicit unions (str | None) instead of relying on an implicit Optional.

-                                  verifier: str = None,
-                                  challenge: str = None) -> str:
+                                  verifier: str | None = None,
+                                  challenge: str | None = None) -> str:
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74a2ca8 and 255e203.

📒 Files selected for processing (8)
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (3 hunks)
  • src/nat/front_ends/console/authentication_flow_handler.py (9 hunks)
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (3 hunks)
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2 hunks)
  • tests/nat/authentication/test_bearer_token_validator.py (2 hunks)
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py (1 hunks)
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py (1 hunks)
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{py,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.{py,yaml,yml}: Configure response_seq as a list of strings; values cycle per call, and [] yields an empty string.
Configure delay_ms to inject per-call artificial latency in milliseconds for nat_test_llm.

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • tests/nat/authentication/test_bearer_token_validator.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py
  • src/nat/front_ends/console/authentication_flow_handler.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.py: Programmatic use: create TestLLMConfig(response_seq=[...], delay_ms=...), add with builder.add_llm("", cfg).
When retrieving the test LLM wrapper, use builder.get_llm(name, wrapper_type=LLMFrameworkEnum.) and call the framework’s method (e.g., ainvoke, achat, call).

**/*.py: In code comments/identifiers use NAT abbreviations as specified: nat for API namespace/CLI, nvidia-nat for package name, NAT for env var prefixes; do not use these abbreviations in documentation
Follow PEP 20 and PEP 8; run yapf with column_limit=120; use 4-space indentation; end files with a single trailing newline
Run ruff check --fix as linter (not formatter) using pyproject.toml config; fix warnings unless explicitly ignored
Respect naming: snake_case for functions/variables, PascalCase for classes, UPPER_CASE for constants
Treat pyright warnings as errors during development
Exception handling: use bare raise to re-raise; log with logger.error() when re-raising to avoid duplicate stack traces; use logger.exception() when catching without re-raising
Provide Google-style docstrings for every public module, class, function, and CLI command; first line concise and ending with a period; surround code entities with backticks
Validate and sanitize all user input, especially in web or CLI interfaces
Prefer httpx with SSL verification enabled by default and follow OWASP Top-10 recommendations
Use async/await for I/O-bound work; profile CPU-heavy paths with cProfile or mprof before optimizing; cache expensive computations with functools.lru_cache or external cache; leverage NumPy vectorized operations when beneficial

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • tests/nat/authentication/test_bearer_token_validator.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py
  • src/nat/front_ends/console/authentication_flow_handler.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All importable Python code must live under src/ (or packages//src/)

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • src/nat/front_ends/console/authentication_flow_handler.py
src/nat/**/*

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Changes in src/nat should prioritize backward compatibility

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • src/nat/front_ends/console/authentication_flow_handler.py

⚙️ CodeRabbit configuration file

This directory contains the core functionality of the toolkit. Changes should prioritize backward compatibility.

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • src/nat/front_ends/console/authentication_flow_handler.py
{src/**/*.py,packages/*/src/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All public APIs must have Python 3.11+ type hints on parameters and return values; prefer typing/collections.abc abstractions; use typing.Annotated when useful

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • src/nat/front_ends/console/authentication_flow_handler.py
**/*

⚙️ CodeRabbit configuration file

**/*: # Code Review Instructions

  • Ensure the code follows best practices and coding standards. - For Python code, follow
    PEP 20 and
    PEP 8 for style guidelines.
  • Check for security vulnerabilities and potential issues. - Python methods should use type hints for all parameters and return values.
    Example:
    def my_function(param1: int, param2: str) -> bool:
        pass
  • For Python exception handling, ensure proper stack trace preservation:
    • When re-raising exceptions: use bare raise statements to maintain the original stack trace,
      and use logger.error() (not logger.exception()) to avoid duplicate stack trace output.
    • When catching and logging exceptions without re-raising: always use logger.exception()
      to capture the full stack trace information.

Documentation Review Instructions - Verify that documentation and comments are clear and comprehensive. - Verify that the documentation doesn't contain any TODOs, FIXMEs or placeholder text like "lorem ipsum". - Verify that the documentation doesn't contain any offensive or outdated terms. - Verify that documentation and comments are free of spelling mistakes, ensure the documentation doesn't contain any

words listed in the ci/vale/styles/config/vocabularies/nat/reject.txt file, words that might appear to be
spelling mistakes but are listed in the ci/vale/styles/config/vocabularies/nat/accept.txt file are OK.

Misc. - All code (except .mdc files that contain Cursor rules) should be licensed under the Apache License 2.0,

and should contain an Apache License 2.0 header comment at the top of each file.

  • Confirm that copyright years are up-to date whenever a file is changed.

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
  • tests/nat/authentication/test_bearer_token_validator.py
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py
  • src/nat/front_ends/console/authentication_flow_handler.py
tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Unit tests reside under tests/ and should use markers defined in pyproject.toml (e.g., integration)

Files:

  • tests/nat/authentication/test_bearer_token_validator.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py

⚙️ CodeRabbit configuration file

tests/**/*.py: - Ensure that tests are comprehensive, cover edge cases, and validate the functionality of the code. - Test functions should be named using the test_ prefix, using snake_case. - Any frequently repeated code should be extracted into pytest fixtures. - Pytest fixtures should define the name argument when applying the pytest.fixture decorator. The fixture
function being decorated should be named using the fixture_ prefix, using snake_case. Example:
@pytest.fixture(name="my_fixture")
def fixture_my_fixture():
pass

Files:

  • tests/nat/authentication/test_bearer_token_validator.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py
{tests/**/*.py,examples/*/tests/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

{tests/**/*.py,examples/*/tests/**/*.py}: Use pytest (with pytest-asyncio for async); name test files test_*.py; test functions start with test_; extract repeated code into fixtures; fixtures must set name in decorator and be named with fixture_ prefix
Mock external services with pytest_httpserver or unittest.mock; do not hit live endpoints
Mark expensive tests with @pytest.mark.slow or @pytest.mark.integration

Files:

  • tests/nat/authentication/test_bearer_token_validator.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py
🧬 Code graph analysis (7)
tests/nat/authentication/test_bearer_token_validator.py (1)
src/nat/authentication/credential_validator/bearer_token_validator.py (1)
  • verify (111-137)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (3)
tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py (3)
  • create_oauth_client (52-66)
  • create_websocket_message (116-143)
  • create_websocket_message (193-194)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2)
  • config (122-123)
  • redirect_uri (1050-1089)
src/nat/front_ends/console/authentication_flow_handler.py (1)
  • _create_authorization_url (112-141)
tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py (2)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (1)
  • redirect_uri (1050-1089)
tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py (1)
  • mock_server (77-81)
tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py (1)
src/nat/front_ends/console/authentication_flow_handler.py (2)
  • construct_oauth_client (91-110)
  • authenticate (75-88)
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (1)
src/nat/data_models/authentication.py (2)
  • AuthResult (200-251)
  • BearerTokenCred (158-165)
tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py (2)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (3)
  • create_oauth_client (66-78)
  • WebSocketAuthenticationFlowHandler (48-143)
  • authenticate (59-64)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (4)
  • config (122-123)
  • redirect_uri (1050-1089)
  • _add_flow (1099-1101)
  • _remove_flow (1103-1105)
src/nat/front_ends/console/authentication_flow_handler.py (2)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2)
  • redirect_uri (1050-1089)
  • config (122-123)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (1)
  • _create_authorization_url (80-109)
🪛 Ruff (0.13.1)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py

1082-1082: Do not catch blind exception: Exception

(BLE001)

tests/nat/authentication/test_bearer_token_validator.py

336-336: Possible hardcoded password assigned to: "token"

(S105)

src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py

76-76: Avoid specifying long messages outside the exception class

(TRY003)


78-78: Avoid specifying long messages outside the exception class

(TRY003)


84-84: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


85-85: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


107-107: Consider moving this statement to an else block

(TRY300)


109-109: Avoid specifying long messages outside the exception class

(TRY003)


135-135: Avoid specifying long messages outside the exception class

(TRY003)

tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py

36-36: Possible hardcoded password assigned to argument: "client_secret"

(S106)


38-38: Possible hardcoded password assigned to argument: "token_url"

(S106)


159-159: String contains ambiguous е (CYRILLIC SMALL LETTER IE). Did you mean e (LATIN SMALL LETTER E)?

(RUF001)


160-160: String contains ambiguous е (CYRILLIC SMALL LETTER IE). Did you mean e (LATIN SMALL LETTER E)?

(RUF001)


194-194: Unused method argument: attack_description

(ARG002)


370-370: Unpacked variable returned_state is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


420-420: Unused method argument: test_case_name

(ARG002)


456-456: Create your own exception

(TRY002)


456-456: Avoid specifying long messages outside the exception class

(TRY003)


488-488: Unused function argument: description

(ARG001)


572-572: Possible hardcoded password assigned to argument: "client_secret"

(S106)


603-603: Unpacked variable state is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py

164-164: Unused function argument: mock_server

(ARG001)


173-173: Unused method argument: cfg

(ARG002)


175-175: Avoid specifying long messages outside the exception class

(TRY003)


179-179: Possible hardcoded password assigned to argument: "client_secret"

(S106)


181-181: Possible hardcoded password assigned to argument: "token_url"

(S106)

src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py

67-67: Do not catch blind exception: Exception

(BLE001)

tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py

181-181: Unused function argument: mock_server

(ARG001)


181-181: Unused function argument: tmp_path

(ARG001)


207-207: Possible hardcoded password assigned to argument: "token_url"

(S106)

src/nat/front_ends/console/authentication_flow_handler.py

106-106: Consider moving this statement to an else block

(TRY300)


108-108: Avoid specifying long messages outside the exception class

(TRY003)


110-110: Avoid specifying long messages outside the exception class

(TRY003)


116-116: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


117-117: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


139-139: Consider moving this statement to an else block

(TRY300)


141-141: Avoid specifying long messages outside the exception class

(TRY003)


195-195: Do not catch blind exception: Exception

(BLE001)


202-202: Avoid specifying long messages outside the exception class

(TRY003)


223-223: Docstring contains ambiguous (NON-BREAKING HYPHEN). Did you mean - (HYPHEN-MINUS)?

(RUF002)


246-246: Do not catch blind exception: Exception

(BLE001)


278-278: Docstring contains ambiguous (NON-BREAKING HYPHEN). Did you mean - (HYPHEN-MINUS)?

(RUF002)

@ericevans-nv ericevans-nv removed improvement Improvement to existing functionality external This issue was filed by someone outside of the NeMo Agent toolkit team labels Sep 27, 2025
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2)

191-206: Fix filter removal: current code leaks a new filter per request.

You add and remove different LogFilter instances; the one added is never removed, degrading observability over time.

Apply this diff:

     async def _suppress_authentication_logs(self, request: Request,
                                             call_next: Callable[[Request], Awaitable[Response]]) -> Response:
         """
-        Intercepts authentication request and supreses logs that contain sensitive data.
+        Intercepts authentication request and suppresses logs that contain sensitive data.
         """
         from nat.utils.log_utils import LogFilter
 
         logs_to_suppress: list[str] = []
 
         if (self.front_end_config.oauth2_callback_path):
             logs_to_suppress.append(self.front_end_config.oauth2_callback_path)
 
-        logging.getLogger("uvicorn.access").addFilter(LogFilter(logs_to_suppress))
+        uvicorn_logger = logging.getLogger("uvicorn.access")
+        log_filter = LogFilter(logs_to_suppress)
+        uvicorn_logger.addFilter(log_filter)
         try:
             response = await call_next(request)
         finally:
-            logging.getLogger("uvicorn.access").removeFilter(LogFilter(logs_to_suppress))
+            uvicorn_logger.removeFilter(log_filter)
 
         return response

As per coding guidelines


1061-1067: Make state single-use with atomic pop and return 400 on invalid state.

Reading without removal allows replay; pop under lock enforces one-time use and mitigates CSRF replay attempts.

Apply this diff:

             async with self._outstanding_flows_lock:
-                if not state or state not in self._outstanding_flows:
-                    return "Invalid state. Please restart the authentication process."
-
-                flow_state = self._outstanding_flows[state]
+                if not state or state not in self._outstanding_flows:
+                    from fastapi.responses import HTMLResponse
+                    return HTMLResponse(
+                        content="Invalid state. Please restart the authentication process.",
+                        status_code=400,
+                        headers={"Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store, max-age=0, must-revalidate"},
+                    )
+
+                # One-time use: remove state atomically to prevent replay.
+                flow_state = self._outstanding_flows.pop(state)

As per coding guidelines

🧹 Nitpick comments (3)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (3)

40-42: Catch the concrete Authlib OAuth2 error type.

Catching OAuth2Error ensures .error and .description fields are present and avoids attribute surprises across Authlib versions.

Apply this diff:

-import httpx
-from authlib.common.errors import AuthlibBaseError as OAuthError
+import httpx
+from authlib.oauth2.rfc6749.errors import OAuth2Error as OAuthError

Based on learnings


1085-1089: Harden caching policy on the auth callback page.

Use Cache-Control: no-store, max-age=0, must-revalidate to prevent intermediaries from storing the page.

Apply this diff:

             return HTMLResponse(content=AUTH_REDIRECT_SUCCESS_HTML,
                                 status_code=200,
                                 headers={
-                                    "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-cache"
+                                    "Content-Type": "text/html; charset=utf-8",
+                                    "Cache-Control": "no-store, max-age=0, must-revalidate",
                                 })

If tests assert the exact header value, adjust expectations accordingly.


1045-1045: Add explicit return type annotation.

Annotate the coroutine to return None for consistency with our typing guidance.

Apply this diff:

-    async def add_authorization_route(self, app: FastAPI):
+    async def add_authorization_route(self, app: FastAPI) -> None:

As per coding guidelines

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 255e203 and 5193b22.

📒 Files selected for processing (1)
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{py,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.{py,yaml,yml}: Configure response_seq as a list of strings; values cycle per call, and [] yields an empty string.
Configure delay_ms to inject per-call artificial latency in milliseconds for nat_test_llm.

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.py: Programmatic use: create TestLLMConfig(response_seq=[...], delay_ms=...), add with builder.add_llm("", cfg).
When retrieving the test LLM wrapper, use builder.get_llm(name, wrapper_type=LLMFrameworkEnum.) and call the framework’s method (e.g., ainvoke, achat, call).

**/*.py: In code comments/identifiers use NAT abbreviations as specified: nat for API namespace/CLI, nvidia-nat for package name, NAT for env var prefixes; do not use these abbreviations in documentation
Follow PEP 20 and PEP 8; run yapf with column_limit=120; use 4-space indentation; end files with a single trailing newline
Run ruff check --fix as linter (not formatter) using pyproject.toml config; fix warnings unless explicitly ignored
Respect naming: snake_case for functions/variables, PascalCase for classes, UPPER_CASE for constants
Treat pyright warnings as errors during development
Exception handling: use bare raise to re-raise; log with logger.error() when re-raising to avoid duplicate stack traces; use logger.exception() when catching without re-raising
Provide Google-style docstrings for every public module, class, function, and CLI command; first line concise and ending with a period; surround code entities with backticks
Validate and sanitize all user input, especially in web or CLI interfaces
Prefer httpx with SSL verification enabled by default and follow OWASP Top-10 recommendations
Use async/await for I/O-bound work; profile CPU-heavy paths with cProfile or mprof before optimizing; cache expensive computations with functools.lru_cache or external cache; leverage NumPy vectorized operations when beneficial

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All importable Python code must live under src/ (or packages//src/)

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
src/nat/**/*

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Changes in src/nat should prioritize backward compatibility

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py

⚙️ CodeRabbit configuration file

This directory contains the core functionality of the toolkit. Changes should prioritize backward compatibility.

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
{src/**/*.py,packages/*/src/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All public APIs must have Python 3.11+ type hints on parameters and return values; prefer typing/collections.abc abstractions; use typing.Annotated when useful

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
**/*

⚙️ CodeRabbit configuration file

**/*: # Code Review Instructions

  • Ensure the code follows best practices and coding standards. - For Python code, follow
    PEP 20 and
    PEP 8 for style guidelines.
  • Check for security vulnerabilities and potential issues. - Python methods should use type hints for all parameters and return values.
    Example:
    def my_function(param1: int, param2: str) -> bool:
        pass
  • For Python exception handling, ensure proper stack trace preservation:
    • When re-raising exceptions: use bare raise statements to maintain the original stack trace,
      and use logger.error() (not logger.exception()) to avoid duplicate stack trace output.
    • When catching and logging exceptions without re-raising: always use logger.exception()
      to capture the full stack trace information.

Documentation Review Instructions - Verify that documentation and comments are clear and comprehensive. - Verify that the documentation doesn't contain any TODOs, FIXMEs or placeholder text like "lorem ipsum". - Verify that the documentation doesn't contain any offensive or outdated terms. - Verify that documentation and comments are free of spelling mistakes, ensure the documentation doesn't contain any

words listed in the ci/vale/styles/config/vocabularies/nat/reject.txt file, words that might appear to be
spelling mistakes but are listed in the ci/vale/styles/config/vocabularies/nat/accept.txt file are OK.

Misc. - All code (except .mdc files that contain Cursor rules) should be licensed under the Apache License 2.0,

and should contain an Apache License 2.0 header comment at the top of each file.

  • Confirm that copyright years are up-to date whenever a file is changed.

Files:

  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
🪛 Ruff (0.13.1)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py

1082-1082: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Pipeline / Check

@coderabbitai coderabbitai bot added the improvement Improvement to existing functionality label Sep 27, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5193b22 and 6e5d55b.

📒 Files selected for processing (1)
  • src/nat/front_ends/console/authentication_flow_handler.py (9 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{py,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.{py,yaml,yml}: Configure response_seq as a list of strings; values cycle per call, and [] yields an empty string.
Configure delay_ms to inject per-call artificial latency in milliseconds for nat_test_llm.

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.py: Programmatic use: create TestLLMConfig(response_seq=[...], delay_ms=...), add with builder.add_llm("", cfg).
When retrieving the test LLM wrapper, use builder.get_llm(name, wrapper_type=LLMFrameworkEnum.) and call the framework’s method (e.g., ainvoke, achat, call).

**/*.py: In code comments/identifiers use NAT abbreviations as specified: nat for API namespace/CLI, nvidia-nat for package name, NAT for env var prefixes; do not use these abbreviations in documentation
Follow PEP 20 and PEP 8; run yapf with column_limit=120; use 4-space indentation; end files with a single trailing newline
Run ruff check --fix as linter (not formatter) using pyproject.toml config; fix warnings unless explicitly ignored
Respect naming: snake_case for functions/variables, PascalCase for classes, UPPER_CASE for constants
Treat pyright warnings as errors during development
Exception handling: use bare raise to re-raise; log with logger.error() when re-raising to avoid duplicate stack traces; use logger.exception() when catching without re-raising
Provide Google-style docstrings for every public module, class, function, and CLI command; first line concise and ending with a period; surround code entities with backticks
Validate and sanitize all user input, especially in web or CLI interfaces
Prefer httpx with SSL verification enabled by default and follow OWASP Top-10 recommendations
Use async/await for I/O-bound work; profile CPU-heavy paths with cProfile or mprof before optimizing; cache expensive computations with functools.lru_cache or external cache; leverage NumPy vectorized operations when beneficial

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All importable Python code must live under src/ (or packages//src/)

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
src/nat/**/*

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Changes in src/nat should prioritize backward compatibility

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py

⚙️ CodeRabbit configuration file

This directory contains the core functionality of the toolkit. Changes should prioritize backward compatibility.

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
{src/**/*.py,packages/*/src/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All public APIs must have Python 3.11+ type hints on parameters and return values; prefer typing/collections.abc abstractions; use typing.Annotated when useful

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
**/*

⚙️ CodeRabbit configuration file

**/*: # Code Review Instructions

  • Ensure the code follows best practices and coding standards. - For Python code, follow
    PEP 20 and
    PEP 8 for style guidelines.
  • Check for security vulnerabilities and potential issues. - Python methods should use type hints for all parameters and return values.
    Example:
    def my_function(param1: int, param2: str) -> bool:
        pass
  • For Python exception handling, ensure proper stack trace preservation:
    • When re-raising exceptions: use bare raise statements to maintain the original stack trace,
      and use logger.error() (not logger.exception()) to avoid duplicate stack trace output.
    • When catching and logging exceptions without re-raising: always use logger.exception()
      to capture the full stack trace information.

Documentation Review Instructions - Verify that documentation and comments are clear and comprehensive. - Verify that the documentation doesn't contain any TODOs, FIXMEs or placeholder text like "lorem ipsum". - Verify that the documentation doesn't contain any offensive or outdated terms. - Verify that documentation and comments are free of spelling mistakes, ensure the documentation doesn't contain any

words listed in the ci/vale/styles/config/vocabularies/nat/reject.txt file, words that might appear to be
spelling mistakes but are listed in the ci/vale/styles/config/vocabularies/nat/accept.txt file are OK.

Misc. - All code (except .mdc files that contain Cursor rules) should be licensed under the Apache License 2.0,

and should contain an Apache License 2.0 header comment at the top of each file.

  • Confirm that copyright years are up-to date whenever a file is changed.

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
🧬 Code graph analysis (1)
src/nat/front_ends/console/authentication_flow_handler.py (2)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2)
  • redirect_uri (1050-1089)
  • config (122-123)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (1)
  • _create_authorization_url (80-109)
🪛 Ruff (0.13.1)
src/nat/front_ends/console/authentication_flow_handler.py

106-106: Consider moving this statement to an else block

(TRY300)


108-108: Avoid specifying long messages outside the exception class

(TRY003)


110-110: Avoid specifying long messages outside the exception class

(TRY003)


116-116: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


117-117: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


139-139: Consider moving this statement to an else block

(TRY300)


141-141: Avoid specifying long messages outside the exception class

(TRY003)


195-195: Do not catch blind exception: Exception

(BLE001)


202-202: Avoid specifying long messages outside the exception class

(TRY003)


223-223: Docstring contains ambiguous (NON-BREAKING HYPHEN). Did you mean - (HYPHEN-MINUS)?

(RUF002)


248-248: Do not catch blind exception: Exception

(BLE001)


281-281: Docstring contains ambiguous (NON-BREAKING HYPHEN). Did you mean - (HYPHEN-MINUS)?

(RUF002)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Pipeline / Check

@ericevans-nv ericevans-nv removed the improvement Improvement to existing functionality label Sep 29, 2025
Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
@coderabbitai coderabbitai bot added the improvement Improvement to existing functionality label Sep 29, 2025
@ericevans-nv ericevans-nv removed the improvement Improvement to existing functionality label Sep 29, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/nat/front_ends/console/authentication_flow_handler.py (1)

60-62: Replace the non-breaking hyphen to satisfy lint.

The bullet still uses a non-breaking hyphen (Authorization‑Code), which ruff flags as RUF002. Swap it for a plain ASCII hyphen so the docstring passes lint.

-      • OAuth 2 Authorization‑Code with optional PKCE
+      • OAuth 2 Authorization-Code with optional PKCE

As per coding guidelines.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e5d55b and 41f2061.

📒 Files selected for processing (1)
  • src/nat/front_ends/console/authentication_flow_handler.py (9 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{py,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.{py,yaml,yml}: Configure response_seq as a list of strings; values cycle per call, and [] yields an empty string.
Configure delay_ms to inject per-call artificial latency in milliseconds for nat_test_llm.

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.py: Programmatic use: create TestLLMConfig(response_seq=[...], delay_ms=...), add with builder.add_llm("", cfg).
When retrieving the test LLM wrapper, use builder.get_llm(name, wrapper_type=LLMFrameworkEnum.) and call the framework’s method (e.g., ainvoke, achat, call).

**/*.py: In code comments/identifiers use NAT abbreviations as specified: nat for API namespace/CLI, nvidia-nat for package name, NAT for env var prefixes; do not use these abbreviations in documentation
Follow PEP 20 and PEP 8; run yapf with column_limit=120; use 4-space indentation; end files with a single trailing newline
Run ruff check --fix as linter (not formatter) using pyproject.toml config; fix warnings unless explicitly ignored
Respect naming: snake_case for functions/variables, PascalCase for classes, UPPER_CASE for constants
Treat pyright warnings as errors during development
Exception handling: use bare raise to re-raise; log with logger.error() when re-raising to avoid duplicate stack traces; use logger.exception() when catching without re-raising
Provide Google-style docstrings for every public module, class, function, and CLI command; first line concise and ending with a period; surround code entities with backticks
Validate and sanitize all user input, especially in web or CLI interfaces
Prefer httpx with SSL verification enabled by default and follow OWASP Top-10 recommendations
Use async/await for I/O-bound work; profile CPU-heavy paths with cProfile or mprof before optimizing; cache expensive computations with functools.lru_cache or external cache; leverage NumPy vectorized operations when beneficial

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All importable Python code must live under src/ (or packages//src/)

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
src/nat/**/*

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Changes in src/nat should prioritize backward compatibility

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py

⚙️ CodeRabbit configuration file

This directory contains the core functionality of the toolkit. Changes should prioritize backward compatibility.

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
{src/**/*.py,packages/*/src/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All public APIs must have Python 3.11+ type hints on parameters and return values; prefer typing/collections.abc abstractions; use typing.Annotated when useful

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
**/*

⚙️ CodeRabbit configuration file

**/*: # Code Review Instructions

  • Ensure the code follows best practices and coding standards. - For Python code, follow
    PEP 20 and
    PEP 8 for style guidelines.
  • Check for security vulnerabilities and potential issues. - Python methods should use type hints for all parameters and return values.
    Example:
    def my_function(param1: int, param2: str) -> bool:
        pass
  • For Python exception handling, ensure proper stack trace preservation:
    • When re-raising exceptions: use bare raise statements to maintain the original stack trace,
      and use logger.error() (not logger.exception()) to avoid duplicate stack trace output.
    • When catching and logging exceptions without re-raising: always use logger.exception()
      to capture the full stack trace information.

Documentation Review Instructions - Verify that documentation and comments are clear and comprehensive. - Verify that the documentation doesn't contain any TODOs, FIXMEs or placeholder text like "lorem ipsum". - Verify that the documentation doesn't contain any offensive or outdated terms. - Verify that documentation and comments are free of spelling mistakes, ensure the documentation doesn't contain any

words listed in the ci/vale/styles/config/vocabularies/nat/reject.txt file, words that might appear to be
spelling mistakes but are listed in the ci/vale/styles/config/vocabularies/nat/accept.txt file are OK.

Misc. - All code (except .mdc files that contain Cursor rules) should be licensed under the Apache License 2.0,

and should contain an Apache License 2.0 header comment at the top of each file.

  • Confirm that copyright years are up-to date whenever a file is changed.

Files:

  • src/nat/front_ends/console/authentication_flow_handler.py
🧬 Code graph analysis (1)
src/nat/front_ends/console/authentication_flow_handler.py (2)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2)
  • redirect_uri (1050-1089)
  • config (122-123)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (1)
  • _create_authorization_url (80-109)
🪛 Ruff (0.13.1)
src/nat/front_ends/console/authentication_flow_handler.py

106-106: Consider moving this statement to an else block

(TRY300)


108-108: Avoid specifying long messages outside the exception class

(TRY003)


110-110: Avoid specifying long messages outside the exception class

(TRY003)


139-139: Consider moving this statement to an else block

(TRY300)


141-141: Avoid specifying long messages outside the exception class

(TRY003)


195-195: Do not catch blind exception: Exception

(BLE001)


202-202: Avoid specifying long messages outside the exception class

(TRY003)


223-223: Docstring contains ambiguous (NON-BREAKING HYPHEN). Did you mean - (HYPHEN-MINUS)?

(RUF002)


248-248: Do not catch blind exception: Exception

(BLE001)


281-281: Docstring contains ambiguous (NON-BREAKING HYPHEN). Did you mean - (HYPHEN-MINUS)?

(RUF002)

🔇 Additional comments (3)
src/nat/front_ends/console/authentication_flow_handler.py (3)

221-223: Normalize hyphen usage in the docstring.

This docstring still contains a non-breaking hyphen (in‑process), which triggers ruff RUF002. Please replace it with a regular hyphen.

-        * Else → only build the redirect app and save it to `self._redirect_app`
-                 for in‑process testing.
+        * Else → only build the redirect app and save it to `self._redirect_app`
+                 for in-process testing.

As per coding guidelines.


132-137: Remove the PKCE verifier from the authorization redirect.

Leaking the code_verifier in the authorization request undermines PKCE (and several IdPs reject it outright). RFC 7636 requires that only the challenge go over the wire; the verifier must stay server-side until the token exchange. Please drop the code_verifier kwarg here and continue storing the verifier in flow_state for the later fetch_token call.

-                code_verifier=verifier if config.use_pkce else None,
                 code_challenge=challenge if config.use_pkce else None,

251-251: Swap out the en dash in the success message.

The success string still uses an en dash (), which ruff flags (RUF001) and will break lint. Replace it with a standard hyphen.

-            return "Authentication successful – you may close this tab."
+            return "Authentication successful - you may close this tab."

As per coding guidelines.

@coderabbitai coderabbitai bot added the improvement Improvement to existing functionality label Sep 29, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (4)

55-56: Derive expiry robustly: support expires_in and coerce types.

Some providers return expires_in instead of expires_at, or send timestamps as strings. Handle both.

-from datetime import datetime
-from datetime import timezone
+from datetime import datetime
+from datetime import timezone
+from datetime import timedelta
-            expires_at_ts = new_token_data.get("expires_at")
-            new_expires_at = datetime.fromtimestamp(expires_at_ts, tz=timezone.utc) if expires_at_ts else None
+            expires_at_ts = new_token_data.get("expires_at")
+            expires_in = new_token_data.get("expires_in")
+            if expires_at_ts:
+                new_expires_at = datetime.fromtimestamp(int(expires_at_ts), tz=timezone.utc)
+            elif expires_in:
+                new_expires_at = datetime.now(timezone.utc) + timedelta(seconds=int(expires_in))
+            else:
+                new_expires_at = None

58-62: Guard missing access_token to prevent KeyError.

Some token responses (error or device-code style) may omit access_token. Fail fast and fall back to full auth.

-            new_auth_result = AuthResult(
-                credentials=[BearerTokenCred(token=SecretStr(new_token_data["access_token"]))],
+            try:
+                access_token = new_token_data["access_token"]
+            except KeyError:
+                logger.debug("Token refresh response missing access_token; falling back to full auth.", exc_info=False)
+                return None
+
+            new_auth_result = AuthResult(
+                credentials=[BearerTokenCred(token=SecretStr(access_token))],
                 token_expires_at=new_expires_at,
                 raw=new_token_data,
             )

16-21: Sanitized logging is fine; ensure consistency or drop the logger.

A module logger was added but unused. The diffs above wire it into exception paths. If you choose not to log at all, remove the logger import/definition to avoid dead code.

Also applies to: 33-34


36-43: Add concise docstrings to class/methods (repo guideline).

Per coding guidelines, public classes/functions should have Google-style docstrings. Add a brief description for OAuth2AuthCodeFlowProvider and _attempt_token_refresh/authenticate.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41f2061 and 7b9af5f.

📒 Files selected for processing (1)
  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{py,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.{py,yaml,yml}: Configure response_seq as a list of strings; values cycle per call, and [] yields an empty string.
Configure delay_ms to inject per-call artificial latency in milliseconds for nat_test_llm.

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.py: Programmatic use: create TestLLMConfig(response_seq=[...], delay_ms=...), add with builder.add_llm("", cfg).
When retrieving the test LLM wrapper, use builder.get_llm(name, wrapper_type=LLMFrameworkEnum.) and call the framework’s method (e.g., ainvoke, achat, call).

**/*.py: In code comments/identifiers use NAT abbreviations as specified: nat for API namespace/CLI, nvidia-nat for package name, NAT for env var prefixes; do not use these abbreviations in documentation
Follow PEP 20 and PEP 8; run yapf with column_limit=120; use 4-space indentation; end files with a single trailing newline
Run ruff check --fix as linter (not formatter) using pyproject.toml config; fix warnings unless explicitly ignored
Respect naming: snake_case for functions/variables, PascalCase for classes, UPPER_CASE for constants
Treat pyright warnings as errors during development
Exception handling: use bare raise to re-raise; log with logger.error() when re-raising to avoid duplicate stack traces; use logger.exception() when catching without re-raising
Provide Google-style docstrings for every public module, class, function, and CLI command; first line concise and ending with a period; surround code entities with backticks
Validate and sanitize all user input, especially in web or CLI interfaces
Prefer httpx with SSL verification enabled by default and follow OWASP Top-10 recommendations
Use async/await for I/O-bound work; profile CPU-heavy paths with cProfile or mprof before optimizing; cache expensive computations with functools.lru_cache or external cache; leverage NumPy vectorized operations when beneficial

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All importable Python code must live under src/ (or packages//src/)

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
src/nat/**/*

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Changes in src/nat should prioritize backward compatibility

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py

⚙️ CodeRabbit configuration file

This directory contains the core functionality of the toolkit. Changes should prioritize backward compatibility.

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
{src/**/*.py,packages/*/src/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All public APIs must have Python 3.11+ type hints on parameters and return values; prefer typing/collections.abc abstractions; use typing.Annotated when useful

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
**/*

⚙️ CodeRabbit configuration file

**/*: # Code Review Instructions

  • Ensure the code follows best practices and coding standards. - For Python code, follow
    PEP 20 and
    PEP 8 for style guidelines.
  • Check for security vulnerabilities and potential issues. - Python methods should use type hints for all parameters and return values.
    Example:
    def my_function(param1: int, param2: str) -> bool:
        pass
  • For Python exception handling, ensure proper stack trace preservation:
    • When re-raising exceptions: use bare raise statements to maintain the original stack trace,
      and use logger.error() (not logger.exception()) to avoid duplicate stack trace output.
    • When catching and logging exceptions without re-raising: always use logger.exception()
      to capture the full stack trace information.

Documentation Review Instructions - Verify that documentation and comments are clear and comprehensive. - Verify that the documentation doesn't contain any TODOs, FIXMEs or placeholder text like "lorem ipsum". - Verify that the documentation doesn't contain any offensive or outdated terms. - Verify that documentation and comments are free of spelling mistakes, ensure the documentation doesn't contain any

words listed in the ci/vale/styles/config/vocabularies/nat/reject.txt file, words that might appear to be
spelling mistakes but are listed in the ci/vale/styles/config/vocabularies/nat/accept.txt file are OK.

Misc. - All code (except .mdc files that contain Cursor rules) should be licensed under the Apache License 2.0,

and should contain an Apache License 2.0 header comment at the top of each file.

  • Confirm that copyright years are up-to date whenever a file is changed.

Files:

  • src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py
🧬 Code graph analysis (1)
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (1)
src/nat/data_models/authentication.py (2)
  • AuthResult (200-251)
  • BearerTokenCred (158-165)
🪛 Ruff (0.13.1)
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py

69-69: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Pipeline / Check
🔇 Additional comments (1)
src/nat/authentication/oauth2/oauth2_auth_code_flow_provider.py (1)

21-23: No changes required for Authlib exceptions. The generic except Exception already catches Authlib’s OAuth2Error (and related client exceptions), so both HTTPX and OAuth-protocol errors will trigger the intended fallback.

Signed-off-by: Eric Evans <194135482+ericevans-nv@users.noreply.github.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (1)

83-84: Use explicit type hints with T | None syntax.

Per PEP 484 and modern Python conventions, avoid implicit Optional types.

Apply this diff to use explicit type hints:

    def _create_authorization_url(self,
                                  client: AsyncOAuth2Client,
                                  config: OAuth2AuthCodeFlowProviderConfig,
                                  state: str,
-                                 verifier: str = None,
-                                 challenge: str = None) -> str:
+                                 verifier: str | None = None,
+                                 challenge: str | None = None) -> str:
tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py (4)

371-371: Prefix unused unpacked variable with underscore.

The returned_state variable is unpacked but never used.

Apply this diff:

-        authorization_url, returned_state = oauth_client.create_authorization_url(
+        authorization_url, _ = oauth_client.create_authorization_url(

607-607: Prefix unused unpacked variable with underscore.

The state variable is unpacked but never used.

Apply this diff:

-        authorization_url, state = oauth_client.create_authorization_url(
+        authorization_url, _ = oauth_client.create_authorization_url(

483-483: Remove duplicate @pytest.mark.asyncio decorator.

This test already has @pytest.mark.asyncio on line 483, but if you add the module-level pytestmark, this decorator becomes redundant.

Once you add the module-level pytestmark, you can remove this decorator:

-@pytest.mark.asyncio
 async def test_authorization_code_security_handling(mock_server,

651-651: Remove redundant @pytest.mark.asyncio decorator.

This test already has @pytest.mark.asyncio but will be redundant once module-level marking is added.

Once you add the module-level pytestmark, remove this decorator:

-    @pytest.mark.asyncio
     async def test_validate_authentication_log_suppression(self, caplog):
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b9af5f and 5360bda.

📒 Files selected for processing (3)
  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (3 hunks)
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2 hunks)
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{py,yaml,yml}

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.{py,yaml,yml}: Configure response_seq as a list of strings; values cycle per call, and [] yields an empty string.
Configure delay_ms to inject per-call artificial latency in milliseconds for nat_test_llm.

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
**/*.py

📄 CodeRabbit inference engine (.cursor/rules/nat-test-llm.mdc)

**/*.py: Programmatic use: create TestLLMConfig(response_seq=[...], delay_ms=...), add with builder.add_llm("", cfg).
When retrieving the test LLM wrapper, use builder.get_llm(name, wrapper_type=LLMFrameworkEnum.) and call the framework’s method (e.g., ainvoke, achat, call).

**/*.py: In code comments/identifiers use NAT abbreviations as specified: nat for API namespace/CLI, nvidia-nat for package name, NAT for env var prefixes; do not use these abbreviations in documentation
Follow PEP 20 and PEP 8; run yapf with column_limit=120; use 4-space indentation; end files with a single trailing newline
Run ruff check --fix as linter (not formatter) using pyproject.toml config; fix warnings unless explicitly ignored
Respect naming: snake_case for functions/variables, PascalCase for classes, UPPER_CASE for constants
Treat pyright warnings as errors during development
Exception handling: use bare raise to re-raise; log with logger.error() when re-raising to avoid duplicate stack traces; use logger.exception() when catching without re-raising
Provide Google-style docstrings for every public module, class, function, and CLI command; first line concise and ending with a period; surround code entities with backticks
Validate and sanitize all user input, especially in web or CLI interfaces
Prefer httpx with SSL verification enabled by default and follow OWASP Top-10 recommendations
Use async/await for I/O-bound work; profile CPU-heavy paths with cProfile or mprof before optimizing; cache expensive computations with functools.lru_cache or external cache; leverage NumPy vectorized operations when beneficial

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
src/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All importable Python code must live under src/ (or packages//src/)

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
src/nat/**/*

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Changes in src/nat should prioritize backward compatibility

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py

⚙️ CodeRabbit configuration file

This directory contains the core functionality of the toolkit. Changes should prioritize backward compatibility.

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
{src/**/*.py,packages/*/src/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

All public APIs must have Python 3.11+ type hints on parameters and return values; prefer typing/collections.abc abstractions; use typing.Annotated when useful

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
**/*

⚙️ CodeRabbit configuration file

**/*: # Code Review Instructions

  • Ensure the code follows best practices and coding standards. - For Python code, follow
    PEP 20 and
    PEP 8 for style guidelines.
  • Check for security vulnerabilities and potential issues. - Python methods should use type hints for all parameters and return values.
    Example:
    def my_function(param1: int, param2: str) -> bool:
        pass
  • For Python exception handling, ensure proper stack trace preservation:
    • When re-raising exceptions: use bare raise statements to maintain the original stack trace,
      and use logger.error() (not logger.exception()) to avoid duplicate stack trace output.
    • When catching and logging exceptions without re-raising: always use logger.exception()
      to capture the full stack trace information.

Documentation Review Instructions - Verify that documentation and comments are clear and comprehensive. - Verify that the documentation doesn't contain any TODOs, FIXMEs or placeholder text like "lorem ipsum". - Verify that the documentation doesn't contain any offensive or outdated terms. - Verify that documentation and comments are free of spelling mistakes, ensure the documentation doesn't contain any

words listed in the ci/vale/styles/config/vocabularies/nat/reject.txt file, words that might appear to be
spelling mistakes but are listed in the ci/vale/styles/config/vocabularies/nat/accept.txt file are OK.

Misc. - All code (except .mdc files that contain Cursor rules) should be licensed under the Apache License 2.0,

and should contain an Apache License 2.0 header comment at the top of each file.

  • Confirm that copyright years are up-to date whenever a file is changed.

Files:

  • src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py
  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
  • src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py
tests/**/*.py

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

Unit tests reside under tests/ and should use markers defined in pyproject.toml (e.g., integration)

Files:

  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py

⚙️ CodeRabbit configuration file

tests/**/*.py: - Ensure that tests are comprehensive, cover edge cases, and validate the functionality of the code. - Test functions should be named using the test_ prefix, using snake_case. - Any frequently repeated code should be extracted into pytest fixtures. - Pytest fixtures should define the name argument when applying the pytest.fixture decorator. The fixture
function being decorated should be named using the fixture_ prefix, using snake_case. Example:
@pytest.fixture(name="my_fixture")
def fixture_my_fixture():
pass

Files:

  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
{tests/**/*.py,examples/*/tests/**/*.py}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

{tests/**/*.py,examples/*/tests/**/*.py}: Use pytest (with pytest-asyncio for async); name test files test_*.py; test functions start with test_; extract repeated code into fixtures; fixtures must set name in decorator and be named with fixture_ prefix
Mock external services with pytest_httpserver or unittest.mock; do not hit live endpoints
Mark expensive tests with @pytest.mark.slow or @pytest.mark.integration

Files:

  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
🧠 Learnings (1)
📚 Learning: 2025-09-23T18:39:15.023Z
Learnt from: CR
PR: NVIDIA/NeMo-Agent-Toolkit#0
File: .cursor/rules/general.mdc:0-0
Timestamp: 2025-09-23T18:39:15.023Z
Learning: Applies to {tests/**/*.py,examples/*/tests/**/*.py} : Use pytest (with pytest-asyncio for async); name test files test_*.py; test functions start with test_; extract repeated code into fixtures; fixtures must set name in decorator and be named with fixture_ prefix

Applied to files:

  • tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py
🧬 Code graph analysis (2)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (3)
tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py (3)
  • create_oauth_client (52-66)
  • create_websocket_message (116-143)
  • create_websocket_message (193-194)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (2)
  • config (121-122)
  • redirect_uri (1049-1088)
src/nat/front_ends/console/authentication_flow_handler.py (1)
  • _create_authorization_url (112-141)
tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py (3)
src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (1)
  • redirect_uri (1049-1088)
tests/nat/front_ends/auth_flow_handlers/test_console_flow_handler.py (1)
  • mock_server (77-81)
tests/nat/front_ends/auth_flow_handlers/test_websocket_flow_handler.py (1)
  • mock_server (73-77)
🪛 Ruff (0.13.1)
src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py

75-75: Avoid specifying long messages outside the exception class

(TRY003)


77-77: Avoid specifying long messages outside the exception class

(TRY003)


83-83: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


84-84: PEP 484 prohibits implicit Optional

Convert to T | None

(RUF013)


106-106: Consider moving this statement to an else block

(TRY300)


108-108: Avoid specifying long messages outside the exception class

(TRY003)


134-134: Avoid specifying long messages outside the exception class

(TRY003)

tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py

37-37: Possible hardcoded password assigned to argument: "client_secret"

(S106)


39-39: Possible hardcoded password assigned to argument: "token_url"

(S106)


160-160: String contains ambiguous е (CYRILLIC SMALL LETTER IE). Did you mean e (LATIN SMALL LETTER E)?

(RUF001)


161-161: String contains ambiguous е (CYRILLIC SMALL LETTER IE). Did you mean e (LATIN SMALL LETTER E)?

(RUF001)


195-195: Unused method argument: attack_description

(ARG002)


371-371: Unpacked variable returned_state is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)


421-421: Unused method argument: test_case_name

(ARG002)


457-457: Create your own exception

(TRY002)


457-457: Avoid specifying long messages outside the exception class

(TRY003)


489-489: Unused function argument: description

(ARG001)


575-575: Possible hardcoded password assigned to argument: "client_secret"

(S106)


607-607: Unpacked variable state is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py

1081-1081: Do not catch blind exception: Exception

(BLE001)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Pipeline / Check
🔇 Additional comments (4)
tests/nat/front_ends/auth_flow_handlers/test_oauth_security_tests.py (2)

160-161: LGTM! Cyrillic character testing is intentional.

The Cyrillic 'е' characters on these lines are intentionally used to test Unicode homograph attacks in OAuth redirect URIs. This is excellent security test coverage.


22-28: Critical: Add module-level pytest asyncio marker for async tests.

All tests in this module are async def but lack the necessary pytest-asyncio marking. Without this, pytest will treat them as regular functions returning coroutines, and the tests won't execute properly.

Add this line after the imports to mark all tests in the module:

 from nat.authentication.oauth2.oauth2_auth_code_flow_provider_config import OAuth2AuthCodeFlowProviderConfig
 
+pytestmark = pytest.mark.asyncio
+
 
 # --------------------------------------------------------------------------- #

Alternatively, you could decorate each async test with @pytest.mark.asyncio.

src/nat/front_ends/fastapi/fastapi_front_end_plugin_worker.py (1)

1076-1082: Add logging for error paths and suppress Ruff BLE001.

The error handling correctly distinguishes between OAuth errors, network errors, and general exceptions, but it's missing structured logging before setting the exception. This helps with debugging without re-raising.

Apply this diff to add logging and suppress the Ruff warning:

             except OAuthError as e:
+                logger.error("Authorization server rejected request: %s (%s)", 
+                            getattr(e, "error", e.__class__.__name__), 
+                            getattr(e, "description", str(e)))
                 flow_state.future.set_exception(
                     RuntimeError(f"Authorization server rejected request: {e.error} ({e.description})"))
             except httpx.HTTPError as e:
+                logger.error("Network error during token fetch: %s", e)
                 flow_state.future.set_exception(RuntimeError(f"Network error during token fetch: {e}"))
-            except Exception as e:
+            except Exception as e:  # noqa: BLE001
+                logger.exception("Unexpected error during OAuth callback")
                 flow_state.future.set_exception(RuntimeError(f"Authentication failed: {e}"))

As per coding guidelines

src/nat/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py (1)

99-105: Critical: Remove PKCE verifier from authorization URL to prevent security vulnerability.

The code_verifier must never be sent in the authorization request URL as it defeats the purpose of PKCE. The verifier should only be sent to the token endpoint. Including it in the authorization URL exposes it in browser history, server logs, and referrer headers.

Apply this diff to fix the PKCE vulnerability:

            authorization_url, _ = client.create_authorization_url(
                config.authorization_url,
                state=state,
-               code_verifier=verifier if config.use_pkce else None,
                code_challenge=challenge if config.use_pkce else None,
                **(config.authorization_kwargs or {})
            )

The verifier is already correctly stored in flow_state.verifier for later use at the token exchange step.

@ericevans-nv ericevans-nv removed the feature request New feature or request label Sep 29, 2025
Copy link
Member

@willkill07 willkill07 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving with one question related to user experience.

The tests look great.

@ericevans-nv
Copy link
Contributor Author

/merge

@rapids-bot rapids-bot bot merged commit 8face75 into NVIDIA:develop Sep 29, 2025
16 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improvement to existing functionality non-breaking Non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants