-
Notifications
You must be signed in to change notification settings - Fork 20
Reject unauthenticated when no credentials #360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0b3b893
0c08324
50e6bb3
74d73f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,12 @@ def initialize( | |
| if app_id and not skip_auth: | ||
| self._token_validator = TokenValidator.for_service(app_id) | ||
| logger.debug("JWT validation enabled for %s", self._messaging_endpoint) | ||
| elif not skip_auth: | ||
| logger.warning( | ||
| "No credentials configured and skip_auth is not enabled. " | ||
| "All incoming requests will be rejected. Configure client authentication " | ||
| "to securely receive messages, or set skip_auth=True for local development." | ||
| ) | ||
|
|
||
| self._adapter.register_route("POST", self._messaging_endpoint, self.handle_request) | ||
| self._initialized = True | ||
|
|
@@ -90,24 +96,10 @@ async def handle_request(self, request: HttpRequest) -> HttpResponse: | |
| # Validate JWT token | ||
| authorization = headers.get("authorization") or headers.get("Authorization") or "" | ||
|
|
||
| if self._token_validator and not self._skip_auth: | ||
| if not authorization.startswith("Bearer "): | ||
| return HttpResponse(status=401, body={"error": "Unauthorized"}) | ||
|
|
||
| raw_token = authorization.removeprefix("Bearer ") | ||
| if self._skip_auth: | ||
| # Auth explicitly skipped — use a default token | ||
| service_url = cast(Optional[str], body.get("serviceUrl")) | ||
|
|
||
| try: | ||
| await self._token_validator.validate_token(raw_token, service_url) | ||
| except Exception as e: | ||
| logger.warning(f"JWT token validation failed: {e}") | ||
| return HttpResponse(status=401, body={"error": "Unauthorized"}) | ||
|
|
||
| token: TokenProtocol = cast(TokenProtocol, JsonWebToken(value=raw_token)) | ||
| else: | ||
| # No auth — use a default token | ||
| service_url = cast(Optional[str], body.get("serviceUrl")) | ||
| token = cast( | ||
| token: TokenProtocol = cast( | ||
| TokenProtocol, | ||
| SimpleNamespace( | ||
| app_id="", | ||
|
|
@@ -119,6 +111,28 @@ async def handle_request(self, request: HttpRequest) -> HttpResponse: | |
| is_expired=lambda: False, | ||
| ), | ||
| ) | ||
| elif not self._token_validator: | ||
| # No credentials configured — reject the request | ||
| logger.error( | ||
| "No credentials configured. Configure client authentication " | ||
| "to securely receive messages, or set skip_auth=True to allow " | ||
| "unauthenticated requests." | ||
| ) | ||
heyitsaamir marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return HttpResponse(status=401, body={"error": "Authentication not configured"}) | ||
| else: | ||
| if not authorization.startswith("Bearer "): | ||
| return HttpResponse(status=401, body={"error": "Unauthorized"}) | ||
|
|
||
| raw_token = authorization.removeprefix("Bearer ") | ||
| service_url = cast(Optional[str], body.get("serviceUrl")) | ||
|
|
||
| try: | ||
| await self._token_validator.validate_token(raw_token, service_url) | ||
| except Exception as e: | ||
| logger.warning("JWT token validation failed: %s", e) | ||
| return HttpResponse(status=401, body={"error": "Unauthorized"}) | ||
|
Comment on lines
+131
to
+133
|
||
|
|
||
| token = cast(TokenProtocol, JsonWebToken(value=raw_token)) | ||
|
|
||
| core_activity = CoreActivity.model_validate(body) | ||
| activity_type = core_activity.type or "unknown" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will emit an error on every request, while the TS instead logs a warning on startup and then after that returns 401 silently. Should we align behavior?