fix(flags): Deterministic project selection for the remote_config endpoint - #36154
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR implements deterministic project selection for the remote_config endpoint by adding support for POST requests and project API token validation. This fixes an issue where personal access tokens would route to whichever project the user last visited.
- Enhanced
ProjectSecretAPIKeyAuthenticationto validate project API tokens in request bodies - Updated the feature flag endpoint to accept both GET and POST methods
- Modified project routing logic to handle request body tokens for POST/PUT/PATCH methods
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| posthog/auth.py | Added security validation to ensure project API tokens in request body match authenticated projects |
| posthog/api/test/test_authentication.py | Added comprehensive test coverage for the new authentication validation scenarios |
| posthog/api/routing.py | Updated team resolution logic to check request body for tokens on POST/PUT/PATCH methods |
| posthog/api/feature_flag.py | Extended remote_config endpoint to support POST requests alongside existing GET support |
Comments suppressed due to low confidence (1)
posthog/api/test/test_authentication.py:1082
- The test is catching a generic Exception instead of the specific AuthenticationFailed exception that should be raised. This makes the test less precise and could pass if a different exception is thrown.
with self.assertRaises(Exception) as context:
There was a problem hiding this comment.
Greptile Summary
This PR fixes a critical issue with the remote_config endpoint where personal API keys would route to whichever project the user last visited rather than the intended project. The solution introduces deterministic project selection by enabling POST requests with a project API token in the request body.
The key changes include:
-
Enhanced endpoint support: The
remote_configendpoint inposthog/api/feature_flag.pynow accepts both GET and POST methods, with POST allowing project specification via request body -
Request routing updates: Modified
_get_team_from_request()inposthog/api/routing.pyto conditionally pass request data toget_token()for POST/PUT/PATCH methods, enabling project token extraction from request bodies -
Security validation: Added authentication checks in
ProjectSecretAPIKeyAuthenticationclass inposthog/auth.pyto ensure any project API key provided in the request body matches the team associated with the secret API key used for authentication -
Comprehensive testing: Added unit tests in
posthog/api/test/test_authentication.pycovering scenarios with matching keys, mismatched keys, and no keys in the request body
The implementation maintains full backward compatibility - existing GET requests continue to work with the @current project behavior, while new POST requests provide deterministic routing. This fits into PostHog's broader authentication and project management system by extending the existing token validation mechanisms to handle multi-project scenarios more reliably.
Confidence score: 4/5
- This PR is safe to merge with minimal risk as it maintains backward compatibility while fixing a legitimate routing issue
- Score reflects solid implementation with comprehensive testing and proper security validation, though the complexity of authentication logic requires careful attention
- Pay close attention to the authentication validation logic in
posthog/auth.pyto ensure the security checks work correctly across different authentication scenarios
4 files reviewed, 1 comment
1ce9c28 to
709a43c
Compare
Updates remote_config to always make POST requests with the project API key in the request body for deterministic project selection and validation. - Modified remote_config() to use POST instead of GET - Always include project_api_key parameter in request body - Ensures deterministic routing for personal API keys - Validates secret API keys match expected project - Updated tests to reflect new behavior This aligns with backend changes in PostHog/posthog#36154
5b284ad to
ab8a10a
Compare
|
Hmm, test failures seem unrelated to the changes in this PR. |
90d96b6 to
b475fe7
Compare
b475fe7 to
c95793a
Compare
|
@benjackwhite Added you because this touches the project secret api token logic. |
remote_config endpointremote_config and local_evaluation endpoint
d9a3140 to
c95793a
Compare
remote_config and local_evaluation endpointremote_config endpoint
Updates `remote_config` to always make POST requests with the project API key in the request body for deterministic project selection and validation. - Modified remote_config() to use POST instead of GET - Always include `project_api_key` parameter in request body - Ensures deterministic routing for personal API keys - Validates secret API keys match expected project - Updated tests to reflect new behavior This aligns with backend changes in PostHog/posthog#36154
6eb2883 to
e881a4d
Compare
…lidation Move project secret API key team validation from authentication to permissions layer for better architectural separation of concerns. Changes: - Enhanced ProjectSecretAPITokenPermission to validate authenticated team matches resolved team - Added comprehensive test for cross-team access prevention with secret API keys - Maintains security while following proper authentication vs authorization patterns This prevents secret API keys from accessing other teams' data when project_api_key is provided in request body, while still allowing personal API keys to deterministically override team selection with proper user membership validation.
If "project_api_key" is in the request body for a `POST`, `PATCH`, or `PUT` request, we use that as the project token instead of the default team associated with the personal access token.
e881a4d to
6280b2b
Compare
|
Changing |
Adds a means for deterministic project selection when calling the
remote_configendpoint.Problem
See #35303 for more context, but in-short,
remote_configendpoint is accessed with aGETrequest to/api/projects/@current/feature_flags/unencrypted-remote-config-setting/remote_config/When using a personal access token for authentication, this causes the request to route to whichever project the user the token belongs to last visited.
Fixes #35303
Changes
remote_configto supportPOSTrequests.POSTrequest occurs, look in the request body forproject_api_keyto override the@currenttoken.ProjectSecretAPIKeyAuthenticationto validate that the token team and resolved team match.The changes should be backwards compatible. So if somebody had a need for the project switching ability of the
@currentURL, they still get that behavior when making a GET request.I'll update the SDKs to make a POST request and pass the project api token in the request body.
How did you test this code?
Manually.
Unit Tests.
GETpersonal_api_key, no request body. Expect: returns last visited projectGETpersonal_api_key, api_key in request body. Expect: returns last visited projectPOSTpersonal_api_key, no request body. Expect: returns last visited projectPOSTpersonal_api_key, api_key in request body. Expect: returns project with api_keyPOSTpersonal_api_key, api_key for different project in request body. Expect: Auth errorGETsecret_api_key, no request body. Expect: returns project associated with the keyGETsecret_api_key, api_key in request body. Expect: returns project associated with the keyPOSTsecret_api_key, no request body. Expect: returns project associated with the keyPOSTsecret_api_key, api_key in request body. Expect: returns project associated with the keyPOSTsecret_api_key, api_key for a different project in request body. Expect: Auth error👉 Stay up-to-date with PostHog coding conventions for a smoother review.
Client SDKs that need to be updated
posthog-python- fix(flags): Pass project API key inremote_configrequests posthog-python#303posthog-dotnetposthog-goposthog-elixirposthog-nodeposthog-phpposthog-rubyposthog-rust