Skip to content

Conversation

@divu777
Copy link

@divu777 divu777 commented Apr 28, 2025

Issue

Fixes #357

What I changed

  • Added proper error handling when validating API keys.
  • Throw clear errors instead of just returning None silently.
  • Introduced custom exceptions for better understanding (invalid format, not found, etc.).
  • Cleaned up Secret Manager error handling.

Summary by CodeRabbit

  • New Features

    • Added support for configuring the API key secret prefix via an environment variable.
  • Bug Fixes

    • Improved error handling for invalid and missing API keys, providing clearer feedback when issues occur.
    • Enhanced API key validation to return specific error messages for invalid formats.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Apr 28, 2025

## Walkthrough

The changes introduce a configurable secret prefix for API keys using the new `API_KEY_SECRET_PREFIX` environment variable, defaulting to "sk-". The `APIKeyService` class now raises custom exceptions (`InvalidAPIKeyFormatError`, `APIKeyNotFoundError`) for different validation failures instead of returning `None`. Exception handling in the `revoke_api_key` method is refined to specifically catch the `NotFound` exception. The `.env.template` file is updated to include the new environment variable. Additionally, the API router now explicitly handles the `InvalidAPIKeyFormatError` to return a 401 HTTP error with a specific message.

## Changes

| File(s)                         | Change Summary                                                                                                  |
|---------------------------------|-----------------------------------------------------------------------------------------------------------------|
| .env.template                   | Added `API_KEY_SECRET_PREFIX` environment variable placeholder.                                                  |
| app/modules/auth/api_key_service.py | Added custom exception classes for API key validation errors, made secret prefix configurable, updated `validate_api_key` to raise exceptions instead of returning `None`, and refined exception handling in `revoke_api_key`. |
| app/api/router.py               | Updated `get_api_key_user` function to catch `InvalidAPIKeyFormatError` and raise a 401 HTTP error with a specific message and header. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant APIKeyService
    participant DB
    participant API_Router

    Client->>API_Router: get_api_key_user(api_key)
    API_Router->>APIKeyService: validate_api_key(api_key, db)
    APIKeyService->>APIKeyService: Check prefix (from env or default)
    alt Invalid prefix
        APIKeyService-->>API_Router: Raise InvalidAPIKeyFormatError
        API_Router-->>Client: 401 HTTP Error "Invalid API key format"
    else Valid prefix
        APIKeyService->>APIKeyService: Hash API key
        APIKeyService->>DB: Query for hashed key
        alt Key not found
            APIKeyService-->>API_Router: Raise APIKeyNotFoundError
            API_Router-->>Client: 401 HTTP Error "Invalid API key or user not found"
        else Key found
            APIKeyService-->>API_Router: Return user info
            API_Router-->>Client: Return user info
        end
    end

Assessment against linked issues

Objective Addressed Explanation
Enhance error messaging for invalid API key format and not found (357)
Modify return statements in validate_api_key to provide structured error messages/exceptions (357)
Add unit tests for error handling in validate_api_key (357) No test changes are shown in this PR; unclear if tests were added elsewhere.

Possibly related PRs

Suggested reviewers

  • dhirenmathur

Poem

A secret prefix, now set with ease,
API keys checked with expertise.
No more silence when things go wrong—
Exceptions sing a clearer song!
With custom errors, bugs take flight,
This bunny hops with pure delight.
🐇✨


<!-- walkthrough_end -->

<!-- announcements_start -->

> [!NOTE]
> <details>
> <summary>⚡️ AI Code Reviews for VS Code, Cursor, Windsurf</summary>
> 
> CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
> Learn more [here](http://coderabbit.ai/ide).
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 6d6a9e0026a00640ca1586ea8e13956db8ee8b65 and 44615eadd1df237cb97942e05e2e067d0aafebbe.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `app/api/router.py` (2 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* app/api/router.py

</details>

</details>
<!-- internal state start -->


<!-- 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A=== -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=potpie-ai/potpie&utm_content=396):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Contributor

@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

🧹 Nitpick comments (2)
.env.template (1)

34-34: Good addition of configurable API key prefix.

Adding the API_KEY_SECRET_PREFIX environment variable improves flexibility by allowing customization of the API key prefix without code changes.

Consider adding a brief comment to document the purpose and expected format of this variable, for example:

-API_KEY_SECRET_PREFIX=
+# Prefix for API keys (default: "sk-" if not specified)
+API_KEY_SECRET_PREFIX=
app/modules/auth/api_key_service.py (1)

114-114: Update method signature to reflect exception behavior.

The method now raises exceptions instead of returning None in error cases, but the type annotation doesn't reflect this change.

-    async def validate_api_key(api_key: str, db: Session) -> dict:
+    async def validate_api_key(api_key: str, db: Session) -> dict:
+        """Validate an API key and return user info if valid.
+        
+        Raises:
+            InvalidAPIKeyFormatError: If the API key does not start with the expected prefix
+            APIKeyNotFoundError: If no matching API key is found in the database
+        """
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fdf19ac and 90a9ae2.

📒 Files selected for processing (2)
  • .env.template (1 hunks)
  • app/modules/auth/api_key_service.py (4 hunks)
🔇 Additional comments (5)
app/modules/auth/api_key_service.py (5)

13-14: Appropriate import for specific exception handling.

Good improvement to import the specific NotFound exception instead of catching generic exceptions.


16-25: Great addition of custom exception classes.

Creating a hierarchy of custom exceptions with a base class and specific error types is an excellent practice that improves error handling clarity.


29-29: Good implementation of configurable secret prefix.

Making the secret prefix configurable via environment variable with a sensible default value of "sk-" improves flexibility while maintaining backward compatibility.


133-133: Improved error handling with specific exceptions.

Raising APIKeyNotFoundError with a clear message is more informative than returning None and enforces proper error handling.

As with the previous exception, ensure all existing callers are updated to handle this exception.


162-162: More precise exception handling.

Catching the specific NotFound exception rather than a generic exception is a good practice. This avoids masking unexpected errors while still handling the expected case where a secret doesn't exist.

Copy link
Contributor

@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 (1)
app/api/router.py (1)

66-74: Improve exception handling by preserving the exception chain

The implementation correctly catches the InvalidAPIKeyFormatError and raises an appropriate HTTP exception with a clear error message. However, the static analysis tool suggests using raise ... from err or raise ... from None to preserve the exception chain, which is useful for debugging.

    try:
        user = await APIKeyService.validate_api_key(x_api_key, db)
-    except InvalidAPIKeyFormatError:
+    except InvalidAPIKeyFormatError as err:
        raise HTTPException(
            status_code=401,
            detail="Invalid API key format",
            headers={"WWW-Authenticate": "ApiKey"},
-        )
+        ) from err

Also, consider explicitly handling APIKeyNotFoundError if it's raised by validate_api_key() as mentioned in the PR summary, instead of relying on the subsequent if not user: check.

🧰 Tools
🪛 Ruff (0.8.2)

69-73: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90a9ae2 and 6d6a9e0.

📒 Files selected for processing (1)
  • app/api/router.py (2 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
app/api/router.py

69-73: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)

🔇 Additional comments (1)
app/api/router.py (1)

10-10: LGTM - Good addition of InvalidAPIKeyFormatError import

The import has been correctly updated to include the new custom exception class, which supports the improved error handling implementation.

@divu777
Copy link
Author

divu777 commented May 16, 2025

@dhirenmathur hey dhiren raised this PR for a while now , would love to know your thoughts about it . Like did a follow same pattern as you guys or not . Get back to me whenever you get the time .

@dhirenmathur dhirenmathur requested review from kinshuksinghbist and nndn and removed request for nndn May 21, 2025 12:47
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Error Handling for API Key Validation (api_key_service.py)

2 participants