Skip to content
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

feat!: utilize async lock to overcome dangerous race conditions #189

Merged
merged 1 commit into from
Nov 4, 2024

Conversation

tomasvotava
Copy link
Owner

@tomasvotava tomasvotava commented Aug 13, 2024

Brought into light by @parikls in #186

Closes #186

Summary by CodeRabbit

  • New Features

    • Enhanced Single Sign-On (SSO) functionality with support for asynchronous context management.
    • Transition from tox to poe for running tests, streamlining the testing process.
  • Bug Fixes

    • Improved handling of potential race conditions in SSO provider interactions.
  • Documentation

    • Updated CONTRIBUTING.md to remove redundant test instructions and simplify contributor guidelines.
    • Modifications to various documentation files to reflect changes in SSO function implementations.
  • Chores

    • Updated configuration files to remove tox dependency and include typing-extensions.
  • Tests

    • Added new tests for race condition scenarios in SSO management and integrated security warnings in existing tests.

@tomasvotava tomasvotava added bug Something isn't working security Security-related issues and vulnerabilities. labels Aug 13, 2024
@tomasvotava tomasvotava self-assigned this Aug 13, 2024
Copy link

codecov bot commented Aug 13, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 94.99%. Comparing base (ff4438a) to head (981537c).
Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #189      +/-   ##
==========================================
+ Coverage   94.75%   94.99%   +0.23%     
==========================================
  Files          21       21              
  Lines         496      539      +43     
==========================================
+ Hits          470      512      +42     
- Misses         26       27       +1     
Files with missing lines Coverage Δ
fastapi_sso/sso/base.py 96.58% <100.00%> (+0.24%) ⬆️

@tomasvotava
Copy link
Owner Author

@coderabbitai full review

Copy link

coderabbitai bot commented Aug 19, 2024

Actions performed

Full review triggered.

Copy link

coderabbitai bot commented Aug 19, 2024

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update enhances the FastAPI SSO library by transitioning to asynchronous context management for handling Single Sign-On (SSO) processes, addressing potential race conditions that could lead to security issues. Key changes include the use of async with for resource management and the introduction of new warning mechanisms to enforce proper usage patterns. The documentation and testing structures have also been streamlined to support these improvements, promoting better practices in managing user authentication.

Changes

Files Change Summary
.gitignore Added requirements.txt and .python-version to ignore list.
CONTRIBUTING.md Removed tox instructions, focusing solely on poe test.
docs/... Updated functions for Google SSO to use asynchronous context management.
examples/... Changed SSO context management to asynchronous for various providers.
fastapi_sso/sso/base.py Introduced async context management in SSOBase, adding new methods and a security warning.
pyproject.toml Removed tox dependency and added typing-extensions.
tests/test_base.py Integrated SecurityWarning for async context misuse in tests.
tests/test_openid_responses.py Modified tests to include new SSO providers and switched to asynchronous context management.
tests/test_providers.py Updated tests for SSO providers to utilize asynchronous context management.
tests/test_race_condition.py New tests added to validate behavior under concurrent requests.
tox.ini Changed environment setup to fail on missing interpreters and updated commands for dependency installation.

Assessment against linked issues

Objective Addressed Explanation
Race conditions at scale leading to security issues. ( #186 )
Improve handling of asynchronous context in SSO. ( #186 )
Ensure proper usage of SSO provider methods. ( #186 )

🐰 In the meadow, hopping free,
Async magic, as bright as can be!
With tokens safe and warnings clear,
Our SSO’s strong, hold tight, have no fear.
For every login, no race to chase,
A secure path, a happy place! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @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.

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 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 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 for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.
Early access features: disabled

We are currently testing the following features in early access:

  • Anthropic claude-3-5-sonnet for code reviews: Anthropic claims that the new Claude model has stronger code understanding and code generation capabilities than their previous models. Note: Our default code review model was also updated late last week. Please compare the quality of the reviews between the two models by toggling the early access feature.

Note:

  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.
  • Please join our Discord Community to provide feedback and report issues on the discussion post.

Copy link

@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: 3

Outside diff range, codebase verification and nitpick comments (4)
tests/test_providers_individual.py (1)

2-2: Stylistic Improvement: Added blank line after imports.

The addition of a blank line enhances readability but has no impact on functionality.

tests/test_race_condition.py (1)

36-36: Annotate mutable class attribute with ClassVar.

The post_responses attribute should be annotated with ClassVar to indicate it is a class-level attribute.

- post_responses = []  # list of the responses which a client will return for the `POST` requests
+ post_responses: ClassVar[List[Response]] = []  # list of the responses which a client will return for the `POST` requests
Tools
Ruff

36-36: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)

tests/test_providers.py (2)

158-159: Remove useless expression.

The expression sso.oauth_client is not used and can be removed.

- with pytest.warns(SecurityWarning, match="Please make sure you are using SSO provider in an async context"):
-     sso.oauth_client
Tools
Ruff

159-159: Found useless expression. Either assign it to a variable or remove it.

(B018)


160-160: Avoid hardcoded sensitive information.

The _refresh_token is being set to a hardcoded value. Consider using a mock or fixture for testing purposes.

- sso._refresh_token = "test"
+ sso._refresh_token = mock_refresh_token()
def mock_refresh_token():
    return "mocked_refresh_token"
Tools
Ruff

160-160: Possible hardcoded password assigned to: "_refresh_token"

(S105)

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between ab0966a and 6dfdd08.

Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
Files selected for processing (30)
  • .gitignore (1 hunks)
  • CONTRIBUTING.md (1 hunks)
  • docs/how-to-guides/additional-query-params.md (1 hunks)
  • docs/how-to-guides/additional-scopes.md (1 hunks)
  • docs/how-to-guides/redirect-uri-request-time.md (1 hunks)
  • docs/how-to-guides/state-return-url.md (1 hunks)
  • docs/how-to-guides/use-with-fastapi-security.md (2 hunks)
  • docs/tutorials.md (1 hunks)
  • examples/facebook.py (1 hunks)
  • examples/fitbit.py (2 hunks)
  • examples/generic.py (2 hunks)
  • examples/github.py (2 hunks)
  • examples/gitlab.py (2 hunks)
  • examples/google.py (1 hunks)
  • examples/kakao.py (2 hunks)
  • examples/line.py (2 hunks)
  • examples/linkedin.py (2 hunks)
  • examples/microsoft.py (2 hunks)
  • examples/naver.py (2 hunks)
  • examples/notion.py (2 hunks)
  • examples/twitter.py (2 hunks)
  • examples/yandex.py (2 hunks)
  • fastapi_sso/sso/base.py (12 hunks)
  • pyproject.toml (2 hunks)
  • tests/test_base.py (3 hunks)
  • tests/test_openid_responses.py (3 hunks)
  • tests/test_providers.py (7 hunks)
  • tests/test_providers_individual.py (1 hunks)
  • tests/test_race_condition.py (1 hunks)
  • tox.ini (1 hunks)
Additional context used
Ruff
tests/test_base.py

60-60: Found useless expression. Either assign it to a variable or remove it.

(B018)

tests/test_race_condition.py

36-36: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)

tests/test_providers.py

118-118: Argument name Provider should be lowercase

(N803)


123-123: Argument name Provider should be lowercase

(N803)


128-128: Argument name Provider should be lowercase

(N803)


154-154: Argument name Provider should be lowercase

(N803)


159-159: Found useless expression. Either assign it to a variable or remove it.

(B018)


160-160: Possible hardcoded password assigned to: "_refresh_token"

(S105)

GitHub Check: codecov/patch
fastapi_sso/sso/base.py

[warning] 78-78: fastapi_sso/sso/base.py#L78
Added line #L78 was not covered by tests


[warning] 405-405: fastapi_sso/sso/base.py#L405
Added line #L405 was not covered by tests

Additional comments not posted (62)
tox.ini (3)

4-4: Ensure the availability of all interpreters.

Changing skip_missing_interpreters to false will cause the environment to fail if any specified Python interpreters are missing. This enhances robustness but requires all interpreters to be available.

Ensure that all specified Python interpreters (py38, py39, py310, py311, py312) are available in your testing environment to avoid failures.


11-12: Clarify dependency management approach.

Switching from poetry install to poetry export followed by pip install allows for more explicit dependency management. This can improve reproducibility but requires ensuring that the requirements.txt file is up-to-date and correctly reflects the project's dependencies.

Ensure that the requirements.txt file is generated correctly and includes all necessary dependencies for the project.


15-19: Direct tool invocation enhances modularity.

The change from using poetry run to direct invocation of tools like ruff, black, mypy, pytest, and coverage enhances modularity and control over the testing process. This approach allows for better customization and integration of each tool's features.

docs/how-to-guides/redirect-uri-request-time.md (1)

14-14: Correct use of asynchronous context management.

The transition to async with google_sso ensures proper asynchronous resource management, aligning with best practices for handling I/O-bound tasks in web applications.

examples/fitbit.py (2)

24-24: Correct use of asynchronous context management.

The transition to async with sso in auth_init ensures proper asynchronous handling of the SSO context, enhancing the responsiveness of the application.


31-31: Correct use of asynchronous context management.

The transition to async with sso in auth_callback ensures proper asynchronous handling of the SSO context, enhancing the responsiveness of the application.

docs/how-to-guides/additional-query-params.md (2)

14-14: Correct use of asynchronous context management.

The transition to async with google_sso ensures proper asynchronous resource management, aligning with best practices for handling I/O-bound tasks in web applications.


22-22: Correct use of asynchronous context management.

The transition to async with google_sso in google_callback ensures proper asynchronous handling of the SSO context, enhancing the responsiveness of the application.

examples/github.py (2)

24-24: Correct use of asynchronous context management.

The transition to async with sso in auth_init ensures proper asynchronous handling of the SSO context, enhancing the responsiveness of the application.


31-31: Correct use of asynchronous context management.

The transition to async with sso in auth_callback ensures proper asynchronous handling of the SSO context, enhancing the responsiveness of the application.

examples/yandex.py (2)

24-25: Correct use of async with for non-blocking operations.

The transition to async with sso: ensures that the login redirect process is handled asynchronously, which is crucial for performance in web applications using FastAPI.


31-33: Appropriate use of async with for asynchronous verification.

Using async with sso: in the auth_callback function allows the verification process to be non-blocking, improving the application's ability to handle concurrent requests efficiently.

examples/notion.py (2)

24-25: Adoption of async with for asynchronous context management.

The use of async with sso: in the auth_init function is a necessary change for handling login redirects asynchronously, enhancing performance and scalability.


31-33: Effective use of async with for non-blocking verification.

The async with sso: statement in the auth_callback function ensures that the user verification process is handled asynchronously, which is essential for maintaining responsiveness in high-concurrency environments.

examples/linkedin.py (2)

24-25: Implementation of async with for asynchronous login handling.

The change to async with sso: in auth_init is appropriate for managing login redirects asynchronously, which is beneficial for application performance.


31-33: Use of async with for asynchronous user verification.

The async with sso: in auth_callback ensures that the verification process is non-blocking, aligning with best practices for handling concurrent requests.

examples/line.py (2)

24-26: Transition to async with for asynchronous login initialization.

The use of async with sso: in auth_init is a crucial change for handling login redirects in a non-blocking manner, improving scalability and performance.


31-34: Effective asynchronous context management for user verification.

The async with sso: in auth_callback ensures that the verification process is handled asynchronously, which is essential for maintaining application responsiveness.

examples/twitter.py (2)

24-25: Appropriate use of async with for asynchronous login handling.

The transition to async with sso: in auth_init ensures that login redirects are processed in a non-blocking manner, which is crucial for performance in asynchronous environments.


31-33: Implementation of async with for non-blocking user verification.

Using async with sso: in auth_callback allows the verification process to be asynchronous, enhancing the application's ability to handle multiple concurrent requests.

examples/kakao.py (2)

24-25: LGTM: Asynchronous context management in auth_init.

The transition to async with sso: allows for non-blocking operations, improving performance and responsiveness.


31-32: LGTM: Asynchronous context management in auth_callback.

Using async with sso: ensures that the verification and processing of requests are handled efficiently without blocking the event loop.

examples/naver.py (2)

24-25: LGTM: Asynchronous context management in auth_init.

The use of async with sso: is appropriate for handling asynchronous operations in FastAPI.


31-32: LGTM: Asynchronous context management in auth_callback.

This change supports better scalability and responsiveness by allowing other tasks to proceed while waiting for the SSO operations to complete.

examples/microsoft.py (2)

26-27: LGTM: Asynchronous context management in auth_init.

The use of async with sso: supports non-blocking operations, enhancing performance.


33-34: LGTM: Asynchronous context management in auth_callback.

This change ensures efficient request handling without blocking the event loop.

examples/google.py (2)

24-25: LGTM: Asynchronous context management in auth_init.

The transition to async with sso: is suitable for handling non-blocking operations in FastAPI.


31-33: LGTM: Asynchronous context management in auth_callback.

This change enhances the control flow and logic of the authentication process, promoting better scalability.

examples/facebook.py (2)

26-26: Good use of async with for non-blocking context management.

The transition to async with sso in the auth_init function ensures that the login redirection operation does not block the event loop, which is crucial for maintaining responsiveness in asynchronous applications.


33-33: Effective use of async with for asynchronous verification.

The use of async with sso in the auth_callback function allows for non-blocking verification and processing of login requests, enhancing the application's ability to handle concurrent authentication processes efficiently.

examples/gitlab.py (2)

26-26: Appropriate use of async with for login initialization.

The change to async with sso in the auth_init function is well-suited for asynchronous environments, preventing blocking during the login redirect process.


33-33: Correct application of async with for login verification.

The modification to use async with sso in the auth_callback function supports non-blocking verification, which is essential for handling multiple login requests concurrently.

docs/how-to-guides/state-return-url.md (2)

18-18: Excellent demonstration of async with for login redirection.

Using async with google_sso in the google_login function effectively illustrates how to manage asynchronous contexts, ensuring that login redirection does not block the event loop.


23-23: Clear example of async with for request verification.

The async with google_sso in the google_callback function is a good example of handling asynchronous verification, promoting efficient and responsive authentication workflows.

docs/how-to-guides/additional-scopes.md (2)

17-17: Appropriate use of async with for login redirection.

The use of async with sso in the google_login function ensures that the login process is handled asynchronously, aligning with best practices for non-blocking operations.


22-22: Effective use of async with for request processing and data access.

The async with sso in the google_callback function, combined with httpx.AsyncClient(), demonstrates a comprehensive approach to handling asynchronous operations, from authentication to data retrieval.

examples/generic.py (2)

48-48: Good implementation of async with for login URL generation.

Using async with sso in the sso_login function ensures that the login URL generation is non-blocking, which is important for maintaining application responsiveness.


55-55: Correct use of async with for processing login responses.

The change to async with sso in the sso_callback function supports non-blocking processing of login responses, which is essential for handling multiple requests concurrently.

.gitignore (1)

1-5: LGTM! The .gitignore updates are appropriate.

The addition of requirements.txt and .python-version to .gitignore aligns with modern dependency management practices using pyproject.toml. This helps maintain a clean repository by excluding environment-specific files.

docs/tutorials.md (1)

29-34: LGTM! Transition to async context management is beneficial.

The switch to async with google_sso ensures non-blocking operations, improving the application's ability to handle concurrent requests effectively. This aligns with best practices in modern web frameworks like FastAPI.

pyproject.toml (1)

117-117: LGTM! Dependency updates are appropriate.

The removal of tox and addition of typing-extensions reflect a strategic refinement in dependency management, ensuring compatibility and potentially simplifying the testing process.

tests/test_base.py (1)

4-8: LGTM! Security warnings enhance test robustness.

The addition of SecurityWarning ensures that the SSO provider is used in an async context, which is critical for maintaining security and preventing race conditions.

CONTRIBUTING.md (1)

Line range hint 1-67: LGTM! Simplified testing instructions are clear.

The removal of tox instructions in favor of using poe streamlines the testing process, making it easier for contributors to follow a single method for running tests.

tests/test_race_condition.py (3)

23-32: LGTM!

The Response class is a well-implemented mock for simulating HTTP responses with token data.


35-55: LGTM!

The AsyncClient class effectively simulates an asynchronous HTTP client for testing purposes.

Tools
Ruff

36-36: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)


12-82: LGTM!

The test__race_condition function effectively tests for race conditions by simulating concurrent logins and verifying token handling.

Tools
Ruff

36-36: Mutable class attributes should be annotated with typing.ClassVar

(RUF012)

docs/how-to-guides/use-with-fastapi-security.md (2)

74-74: LGTM!

The transition to async with in the login function aligns with best practices for asynchronous operations.


89-89: LGTM!

The transition to async with in the login_callback function ensures proper asynchronous handling and enhances responsiveness.

tests/test_openid_responses.py (1)

230-231: LGTM!

The use of async with in test_provider_openid_by_response ensures proper asynchronous context management.

tests/test_providers.py (10)

Line range hint 73-77: LGTM!

The use of async with in test_discovery_document ensures proper asynchronous context management.

Tools
Ruff

70-70: Wrong values type in @pytest.mark.parametrize expected list of tuple

Use list of tuple for parameter values

(PT007)


71-71: Argument name Provider should be lowercase

(N803)


Line range hint 82-87: LGTM!

The use of async with in test_login_url_request_time ensures proper asynchronous context management.

Tools
Ruff

80-80: Argument name Provider should be lowercase

(N803)


95-100: LGTM!

The use of async with in test_login_url_construction_time ensures proper asynchronous context management.


Line range hint 103-109: LGTM!

The use of async with in assert_get_login_url_and_redirect ensures proper asynchronous context management.

Tools
Ruff

92-92: Argument name Provider should be lowercase

(N803)


113-116: LGTM!

The use of async with in test_login_url_additional_params ensures proper asynchronous context management.


120-121: LGTM!

The use of async with in test_login_url_state_at_request_time ensures proper asynchronous context management.


125-126: LGTM!

The use of async with in test_login_url_scope_default ensures proper asynchronous context management.


130-131: LGTM!

The use of async with in test_login_url_scope_additional ensures proper asynchronous context management.


148-153: LGTM!

The use of async with in test_process_login ensures proper asynchronous context management.


154-162: LGTM!

The use of async with in test_context_manager_behavior ensures proper asynchronous context management.

Tools
Ruff

154-154: Argument name Provider should be lowercase

(N803)


159-159: Found useless expression. Either assign it to a variable or remove it.

(B018)


160-160: Possible hardcoded password assigned to: "_refresh_token"

(S105)

fastapi_sso/sso/base.py (3)

75-88: LGTM!

The requires_async_context decorator effectively ensures methods are used within an async context, enhancing safety.

Tools
GitHub Check: codecov/patch

[warning] 78-78: fastapi_sso/sso/base.py#L78
Added line #L78 was not covered by tests


119-120: LGTM!

The introduction of _login_lock and _in_stack effectively manages concurrency and prevents race conditions.


421-442: LGTM!

The __aenter__ and __aexit__ methods provide robust async context management, ensuring safe resource handling.

fastapi_sso/sso/base.py Show resolved Hide resolved
fastapi_sso/sso/base.py Show resolved Hide resolved
Repository owner deleted a comment from coderabbitai bot Nov 4, 2024
@tomasvotava tomasvotava marked this pull request as ready for review November 4, 2024 11:48
@tomasvotava tomasvotava merged commit 49fa33a into master Nov 4, 2024
25 checks passed
@tomasvotava tomasvotava deleted the 186-insecure-race-conditions branch November 4, 2024 11:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working security Security-related issues and vulnerabilities.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Race conditions at scale leading to security issues.
1 participant