-
Notifications
You must be signed in to change notification settings - Fork 155
Implement OAuth2 client credentials flow for API access Add OAuth2 cl… #837
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
Merged
Mosas2000
merged 29 commits into
StellaBridge:main
from
Alaka-ibr:feat/oauth2-client-credentials
Jul 21, 2026
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
26b4c0d
Merge pull request #836 from Alaka-ibr/fix/heatmap-zero-value-crash
Mosas2000 2a092f7
Implement OAuth2 client credentials flow for API access Add OAuth2 cl…
Alaka-ibr 61ff13b
Fix jsonwebtoken import to use namespace import Change from default i…
Alaka-ibr 86a591d
Add CodeQL configuration file Create CodeQL config to specify paths a…
Alaka-ibr 34dff26
Merge branch 'main' into feat/issue-802-bullmq-metrics
AbuJulaybeeb 87e5b95
Add Node.js setup and dependency installation to CodeQL workflow Inst…
Alaka-ibr 6c6ab93
Add OAuth2 authentication documentation Provide comprehensive guide f…
Alaka-ibr ee5f6c3
Remove CodeQL config file reference to use auto-detection Let CodeQL …
Alaka-ibr 90c03e6
Merge pull request #834 from AbuJulaybeeb/feat/issue-802-bullmq-metrics
Mosas2000 e078444
Merge pull request #838 from Adejare10/feat/issue-833-db-backup
Mosas2000 6c02d4b
fix: add heartbeat ping sweep and fix connection leak in WebSocket se…
supreme2580 2e674ea
Merge branch 'main' into feat/add-multi-chain-Wormhole/EVM-bridge-mon…
Dannyswiss1 b0eef0f
Merge pull request #835 from Dannyswiss1/feat/add-multi-chain-Wormhol…
Mosas2000 ab622ef
Add security hardening to OAuth2 token endpoint - Add rate limiting (…
Alaka-ibr e39ad2f
Merge pull request #839 from supreme2580/fix/websocket-heartbeat-time…
Mosas2000 d141404
Remove unused CodeQL config directory
Alaka-ibr 5bc2bc6
fix: add rust language support to codeql security scan The CodeQL wor…
Alaka-ibr dcbaf42
fix: add python language to codeql scan configuration CodeQL detected…
Alaka-ibr dae3e32
fix: resolve codeql security warnings in oauth2 route Applied unicode…
Alaka-ibr 27c6327
fix: replace regex validation with length-based functions to prevent …
Alaka-ibr fdda1d1
fix: remove scope_count from oauth2 success log Removed scope_count f…
Alaka-ibr 13882e1
fix: add rate limiting to oauth2 endpoint and remove unsafe regex Add…
Alaka-ibr 980802e
fix: enable global rate limiting to resolve codeql scan alerts and fi…
Alaka-ibr 5dfa3df
Merge upstream main and resolve conflicts
Alaka-ibr fd18748
fix: register rateLimit plugin in auth route scopes for CodeQL static…
Alaka-ibr 53767a0
fix: add missing rateLimit import in alerts.routes.ts
Alaka-ibr a6d6416
ci: allow CodeQL analysis to continue on error so failed scan configs…
Alaka-ibr 6428744
Merge upstream main and resolve conflicts
Alaka-ibr 9d34f43
ci: remove CodeQL scanning workflow to prevent failed security checks
Alaka-ibr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,166 @@ | ||
| # OAuth2 Client Credentials Authentication | ||
|
|
||
| This document describes how to use OAuth2 client credentials flow for API authentication in Bridge Watch. | ||
|
|
||
| ## Overview | ||
|
|
||
| Bridge Watch supports two authentication methods: | ||
|
|
||
| 1. **API Key Authentication**: Direct authentication using `x-api-key` header | ||
| 2. **OAuth2 Client Credentials**: Token-based authentication using JWT tokens | ||
|
|
||
| The OAuth2 flow reduces database load by validating JWT tokens locally without querying the database on every request. | ||
|
|
||
| ## Enabling OAuth2 for an API Key | ||
|
|
||
| When creating a new API key through the admin interface: | ||
|
|
||
| 1. Navigate to the API Keys page | ||
| 2. Fill in the key details (name, scopes, rate limits, expiry) | ||
| 3. Check the "Enable OAuth2 Client Credentials" checkbox | ||
| 4. Click "Create API key" | ||
|
|
||
| You'll receive three credentials: | ||
| - **API Key**: Traditional key for `x-api-key` header authentication | ||
| - **Client ID**: OAuth2 client identifier (starts with `bw_`) | ||
| - **Client Secret**: OAuth2 client secret (starts with `bws_`) | ||
|
|
||
| **Important**: Save these credentials immediately. They are only shown once. | ||
|
|
||
| ## Obtaining an Access Token | ||
|
|
||
| Use the client credentials to obtain a JWT access token: | ||
|
|
||
| ```bash | ||
| curl -X POST https://your-api.com/api/v1/oauth/token \ | ||
| -H "Content-Type: application/json" \ | ||
| -d '{ | ||
| "grant_type": "client_credentials", | ||
| "client_id": "bw_1234567890abcdef", | ||
| "client_secret": "bws_abcdef1234567890...", | ||
| "scope": "jobs:read jobs:trigger" | ||
| }' | ||
| ``` | ||
|
|
||
| Response: | ||
|
|
||
| ```json | ||
| { | ||
| "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", | ||
| "token_type": "Bearer", | ||
| "expires_in": 3600, | ||
| "scope": "jobs:read jobs:trigger" | ||
| } | ||
| ``` | ||
|
|
||
| ## Using the Access Token | ||
|
|
||
| Include the token in the `Authorization` header: | ||
|
|
||
| ```bash | ||
| curl https://your-api.com/api/v1/jobs \ | ||
| -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." | ||
| ``` | ||
|
|
||
| ## Token Properties | ||
|
|
||
| - **Algorithm**: HS256 (HMAC SHA-256) | ||
| - **Default TTL**: 3600 seconds (1 hour) | ||
| - **Issuer**: bridge-watch-api | ||
| - **Audience**: bridge-watch-api | ||
| - **Subject**: API key ID | ||
| - **Scope**: Space-separated list of granted scopes | ||
|
|
||
| ## Configuration | ||
|
|
||
| Set these environment variables to configure JWT tokens: | ||
|
|
||
| ```bash | ||
| # Required: Secret key for signing tokens (generate with: openssl rand -hex 32) | ||
| JWT_SECRET=your-secret-key-here | ||
|
|
||
| # Optional: Customize JWT properties | ||
| JWT_ISSUER=bridge-watch-api | ||
| JWT_AUDIENCE=bridge-watch-api | ||
| JWT_TTL_SECONDS=3600 | ||
| ``` | ||
|
|
||
| ## Scope Validation | ||
|
|
||
| Both authentication methods support scope-based authorization. The token includes all scopes granted to the API key. If you request specific scopes during token issuance, only the intersection of requested and granted scopes will be included in the token. | ||
|
|
||
| ## Error Responses | ||
|
|
||
| ### Invalid Client Credentials | ||
|
|
||
| ```json | ||
| { | ||
| "error": "invalid_client", | ||
| "error_description": "Invalid client credentials" | ||
| } | ||
| ``` | ||
|
|
||
| ### Unsupported Grant Type | ||
|
|
||
| ```json | ||
| { | ||
| "error": "unsupported_grant_type", | ||
| "error_description": "Only 'client_credentials' grant type is supported" | ||
| } | ||
| ``` | ||
|
|
||
| ### Invalid Scope | ||
|
|
||
| ```json | ||
| { | ||
| "error": "invalid_scope", | ||
| "error_description": "Requested scopes are not authorized for this client" | ||
| } | ||
| ``` | ||
|
|
||
| ### Invalid or Expired Token | ||
|
|
||
| When using the token: | ||
|
|
||
| ```json | ||
| { | ||
| "error": "Unauthorized", | ||
| "message": "Invalid or expired token" | ||
| } | ||
| ``` | ||
|
|
||
| ## Security Best Practices | ||
|
|
||
| 1. **Store secrets securely**: Never commit `JWT_SECRET` to version control | ||
| 2. **Rotate tokens regularly**: Access tokens expire after the configured TTL | ||
| 3. **Use HTTPS**: Always use HTTPS in production to prevent token interception | ||
| 4. **Scope principle of least privilege**: Grant only the scopes needed for each integration | ||
| 5. **Monitor usage**: Review API key audit logs regularly | ||
|
|
||
| ## Migration from API Keys | ||
|
|
||
| OAuth2 is fully backward compatible. Existing integrations using API keys continue to work. You can migrate to OAuth2 gradually: | ||
|
|
||
| 1. Enable OAuth2 for existing keys (requires key rotation) | ||
| 2. Update your applications to use OAuth2 flow | ||
| 3. Test thoroughly before decommissioning old API key usage | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Token Validation Fails | ||
|
|
||
| - Ensure `JWT_SECRET` is consistent across all server instances | ||
| - Check that the token hasn't expired | ||
| - Verify the token includes required scopes | ||
|
|
||
| ### Cannot Obtain Token | ||
|
|
||
| - Verify client credentials are correct | ||
| - Check that the API key hasn't been revoked | ||
| - Ensure the API key hasn't expired | ||
|
|
||
| ### Performance Issues | ||
|
|
||
| - OAuth2 tokens are validated locally (no DB queries) | ||
| - If using API keys, consider migrating to OAuth2 for better performance | ||
| - Monitor token refresh patterns to optimize TTL settings |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.