-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Add OAuth proxies #126
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: master
Are you sure you want to change the base?
Conversation
|
The security team is monitoring all repositories for certain keywords. This PR includes the word(s) "oauth" and so security team members have been added as reviewers to take a look. |
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.
Pull Request Overview
This PR adds OAuth proxy functionality to support multiple cryptocurrency exchange providers (Gemini, Bitflyer, Uphold, and Zebpay) with both sandbox and production environments. The proxies handle OAuth authorization redirects and token exchange requests while securely injecting provider credentials server-side.
Key Changes:
- Added OAuth proxy endpoints for four providers with environment-specific configurations
- Implemented nested environment variable configuration using
OAUTH__prefix with double-underscore delimiter - Added comprehensive test suite using respx for HTTP mocking
Reviewed Changes
Copilot reviewed 17 out of 21 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| pyproject.toml | Added respx testing dependency for HTTP mocking |
| poetry.lock | Updated lock file with respx and dependency group changes |
| env.test | Added test environment variables for OAuth provider credentials |
| env.local | Added local development template for OAuth configuration |
| docker-compose.yml | Added Docker Compose setup for application and Redis |
| conftest.py | Added pytest configuration to load test environment variables |
| app/main.py | Registered OAuth router with the FastAPI application |
| app/config.py | Added OAuth configuration with nested environment variable support |
| app/api/oauth/config.py | Defined configuration models for OAuth providers |
| app/api/oauth/models.py | Added Environment enum for sandbox/production |
| app/api/oauth/routes.py | Created main OAuth router aggregating provider routers |
| app/api/oauth/gemini.py | Implemented Gemini OAuth proxy (credentials in JSON body) |
| app/api/oauth/bitflyer.py | Implemented Bitflyer OAuth proxy (credentials in JSON body + Basic Auth) |
| app/api/oauth/uphold.py | Implemented Uphold OAuth proxy (client_id in URL path, Basic Auth) |
| app/api/oauth/zebpay.py | Implemented Zebpay OAuth proxy (nested returnUrl handling, Basic Auth) |
| app/api/oauth/test_gemini.py | Added comprehensive tests for Gemini proxy |
| app/api/oauth/test_bitflyer.py | Added comprehensive tests for Bitflyer proxy |
| app/api/oauth/test_uphold.py | Added comprehensive tests for Uphold proxy |
| app/api/oauth/test_zebpay.py | Added comprehensive tests for Zebpay proxy |
| app/api/oauth/test_helpers.py | Added shared test utilities for URL assertion |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Sets client_id query param inside the returnUrl query parameter | ||
| Example: GET /api/oauth/zebpay/sandbox/auth |
Copilot
AI
Nov 13, 2025
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.
[nitpick] The docstring states "Sets client_id query param inside the returnUrl query parameter" which is accurate but could be clearer about the nested query parameter structure.
Consider updating for better clarity:
"""
Redirect to Zebpay OAuth authorization page.
Injects client_id as a query parameter within the nested returnUrl parameter.
Example: GET /api/oauth/zebpay/sandbox/auth?returnUrl=https://example.com/callback
Result: Redirects to Zebpay with returnUrl containing client_id
"""| Sets client_id query param inside the returnUrl query parameter | |
| Example: GET /api/oauth/zebpay/sandbox/auth | |
| Injects client_id as a query parameter within the nested returnUrl parameter. | |
| Example: GET /api/oauth/zebpay/sandbox/auth?returnUrl=https://example.com/callback | |
| Result: Redirects to Zebpay with returnUrl containing client_id |
| return JSONResponse( | ||
| content=response.json() if response.content else {}, |
Copilot
AI
Nov 13, 2025
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.
The response.json() call can raise JSONDecodeError if the response body is not valid JSON. This should be handled to avoid unhandled exceptions.
Consider wrapping this in a try-except:
try:
content = response.json() if response.content else {}
except ValueError:
content = {}| return JSONResponse( | |
| content=response.json() if response.content else {}, | |
| try: | |
| content = response.json() if response.content else {} | |
| except ValueError: | |
| content = {} | |
| return JSONResponse( | |
| content=content, |
| return JSONResponse( | ||
| content=response.json() if response.content else {}, |
Copilot
AI
Nov 13, 2025
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.
The response.json() call can raise JSONDecodeError if the response body is not valid JSON. This should be handled to avoid unhandled exceptions.
Consider wrapping this in a try-except:
try:
content = response.json() if response.content else {}
except ValueError:
content = {}| return JSONResponse( | |
| content=response.json() if response.content else {}, | |
| try: | |
| content = response.json() if response.content else {} | |
| except ValueError: | |
| content = {} | |
| return JSONResponse( | |
| content=content, |
| async def auth(environment: Environment, request: Request) -> RedirectResponse: | ||
| """ | ||
| Redirect to Uphold OAuth authorization page. | ||
| Sets client_id query param. |
Copilot
AI
Nov 13, 2025
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.
The docstring states "Sets client_id query param" but the implementation actually puts the client_id in the URL path, not as a query parameter. This is misleading.
Update the docstring to match the implementation:
"""
Redirect to Uphold OAuth authorization page.
Sets client_id in the URL path.
Example: GET /api/oauth/uphold/sandbox/auth
"""| Sets client_id query param. | |
| Sets client_id in the URL path. |
|
@onyb are you good to maintain this even though most of it's related to rewards work? |
|
@kdenhartog Yes, we have agreed to maintain this as long as the proxies are related to "web3", "rewards", etc. These endpoints likely won't have the level of traffic that other gate3 endpoints do, so there are no separate scaling needs either. |
onyb
left a comment
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.
Left some minor review comments
…ocker-compose.yml
|
[puLL-Merge] - brave/gate3@126 DescriptionThis PR adds OAuth proxy functionality for four cryptocurrency exchange providers (Gemini, Bitflyer, Uphold, and Zebpay). The implementation provides authentication and token exchange endpoints that act as intermediaries between client applications and OAuth providers, injecting client credentials server-side rather than exposing them to clients. Key changes:
Possible Issues
Security Hotspots
Privacy Hotspots
ChangesChanges
|
onyb
left a comment
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.
Looks good! Please remember to set the environment variables on staging and production before merging this PR. We have auto-deploy setup for this project.
kdenhartog
left a comment
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.
From a security perspective this seems fine. I checked to see if there's any additional providers that support PKCE with authorization code flow. That's the ideal scenario here and we're using it when we can it seems.
The one nit I did have when reading through this is that we could likely refactor this PR so that there's less code here. Most of these implementations are doing the same thing, but with a different URL and query params passed in by the caller.
|
@mschfh asked over DM:
I think it does make sense to validate this just as a low hanging fruit to make sure people don't abuse this API access in some way. |
No description provided.