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

Add support for pop-up based social sign-in (#9399) #9402

Merged

Conversation

ysmoradi
Copy link
Member

@ysmoradi ysmoradi commented Dec 5, 2024

This closes #9399

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new method for JavaScript interop in the JsBridge class, allowing messages to be published from JavaScript.
    • Added a new constant for client-side navigation, enabling smoother transitions between pages.
    • Enhanced navigation capabilities with conditional logic based on application platform.
  • Improvements

    • Implemented security middleware to enhance protection against web vulnerabilities.
    • Updated SignalR hub configuration to support stateful reconnects, improving connection management.
  • Bug Fixes

    • Improved resource management by ensuring proper cleanup of subscriptions to prevent memory leaks.

@ysmoradi ysmoradi requested a review from msynk December 5, 2024 14:34
Copy link

coderabbitai bot commented Dec 5, 2024

Important

Review skipped

Auto incremental reviews are disabled on this repository.

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

The changes in this pull request enhance the functionality and security of the application. Modifications include the addition of new methods for JavaScript interop, improved event handling for navigation, and updates to service registration, particularly regarding SignalR configurations. Security middleware has been introduced to strengthen protection against vulnerabilities. Additionally, a new constant for navigation messages has been added, and a class has been removed to streamline the codebase. Overall, these changes improve resource management, event handling, and security features.

Changes

File Change Summary
src/.../ClientAppCoordinator.cs Added private field unsubscribe and updated OnInitAsync and DisposeAsync methods for subscription management.
src/.../Layout/JsBridge.razor.cs Added public method PublishMessage for JavaScript interop.
src/.../Extensions/IClientCoreServiceCollectionExtensions.cs Updated AddClientCoreProjectServices method to change SignalR configuration.
src/.../Scripts/app.ts Added event listeners for message handling and modified load event listener.
src/.../Services/ClientPubSubMessages.cs Added constant NAVIGATE_TO for client-side navigation.
src/.../Services/DefaultExternalNavigationService.cs Enhanced NavigateToAsync method for different navigation strategies based on the platform.
src/.../Services/PubSubService.cs Updated documentation comment for clarity on service functionality.
src/.../Services/SignalRInfinitiesRetryPolicy.cs Removed class SignalRInfinitiesRetryPolicy and its method.
src/.../Directory.Packages.props Added package version for NWebsec.AspNetCore.Middleware.
src/.../Directory.Packages8.props Added package version for NWebsec.AspNetCore.Middleware.
src/.../Server.Api/Boilerplate.Server.Api.csproj Added package reference for NWebsec.AspNetCore.Middleware.
src/.../Server.Api/Program.Middlewares.cs Updated ConfigureMiddlewares to add security middleware and modified SignalR hub mapping.
src/.../Server.Web/Program.Middlewares.cs Updated ConfigureMiddlewares to add security middleware and improve HTTP status code handling.

Assessment against linked issues

Objective Addressed Explanation
Open login window in a new tab/popup (#9399)

🐇 In the code, new paths arise,
With bridges to JavaScript skies.
Security now guards the way,
As we hop through night and day.
A popup for login, oh what a treat,
In our app, the changes are sweet! 🌟


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>, please review it.
    • 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 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 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.

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: 6

🧹 Outside diff range and nitpick comments (6)
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/DefaultExternalNavigationService.cs (2)

5-5: Consider making Window dimensions configurable.

The Window service is properly injected, but consider making it more flexible by allowing configuration of default dimensions.

+    private const int DEFAULT_POPUP_HEIGHT = 768;
+    private const int DEFAULT_POPUP_WIDTH = 1024;
+    private readonly WindowOptions _windowOptions;
+
     [AutoInject] private readonly Window window = default!;
     [AutoInject] private readonly NavigationManager navigationManager = default!;
+
+    public DefaultExternalNavigationService(IConfiguration configuration)
+    {
+        _windowOptions = configuration
+            .GetSection("ExternalNavigation:WindowOptions")
+            .Get<WindowOptions>() ?? new WindowOptions
+            {
+                Height = DEFAULT_POPUP_HEIGHT,
+                Width = DEFAULT_POPUP_WIDTH
+            };
+    }

16-20: Consider accessibility implications of popup windows.

While the implementation provides good fallback options, popup windows can cause accessibility issues. Consider:

  1. Adding ARIA attributes for screen readers
  2. Ensuring keyboard navigation works in the popup
  3. Providing a user preference to disable popups

Would you like me to provide a more detailed implementation that addresses these accessibility concerns?

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Program.Middlewares.cs (1)

62-62: Consider removing deprecated UseXXssProtection middleware

The X-XSS-Protection header configured by UseXXssProtection is deprecated and ineffective in modern browsers. It's advisable to remove this middleware to simplify the pipeline.

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs (1)

51-51: Consider removing deprecated UseXXssProtection middleware

The X-XSS-Protection header set by UseXXssProtection is deprecated and is no longer supported by modern browsers. Consider removing this middleware to streamline the middleware configuration.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Extensions/IClientCoreServiceCollectionExtensions.cs (2)

146-146: Consider the implications of using stateful reconnect

The change from automatic reconnect to stateful reconnect (WithStatefulReconnect()) has important implications:

  1. Stateful reconnect maintains the connection state during reconnection attempts, which is beneficial for the pop-up based social sign-in scenario as it helps preserve the application state.
  2. However, it consumes more memory as it needs to track the connection state.

Consider implementing a connection state monitoring mechanism to handle scenarios where reconnection attempts fail permanently. This could include:

  • Logging reconnection attempts
  • Implementing a fallback mechanism
  • Notifying users about connection status

Line range hint 149-153: Review WebSocket transport configuration

The code makes good architectural decisions regarding WebSocket transport:

  1. Explicitly disables skip negotiation for Azure SignalR compatibility
  2. Correctly enforces WebSocket transport
  3. Includes helpful comments about avoiding long polling and Server-Sent Events

To support this WebSocket-only approach:

  1. Ensure your deployment environment (IIS/Cloudflare) has WebSocket support enabled
  2. Consider implementing a connection fallback strategy for environments where WebSockets might be blocked
  3. Add monitoring for failed connection attempts to identify environments where WebSocket support is missing
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2c5ea07 and 410b77b.

📒 Files selected for processing (13)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/ClientAppCoordinator.cs (3 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/Layout/JsBridge.razor.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Extensions/IClientCoreServiceCollectionExtensions.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Scripts/app.ts (2 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/ClientPubSubMessages.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/DefaultExternalNavigationService.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/PubSubService.cs (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/SignalRInfinitiesRetryPolicy.cs (0 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages8.props (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Boilerplate.Server.Api.csproj (1 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs (2 hunks)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Program.Middlewares.cs (2 hunks)
💤 Files with no reviewable changes (1)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/SignalRInfinitiesRetryPolicy.cs
✅ Files skipped from review due to trivial changes (1)
  • src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/PubSubService.cs
🔇 Additional comments (11)
src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/ClientPubSubMessages.cs (1)

25-28: LGTM! Well-documented constant addition.

The new NAVIGATE_TO constant is well-documented and follows the existing naming convention. Its purpose aligns with the PR objective of enabling external navigation without app reload.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Services/DefaultExternalNavigationService.cs (1)

16-20: Verify the navigation flow across different browsers.

The popup fallback logic looks good, but we should verify it works consistently across different browsers and scenarios.

✅ Verification successful

Let me analyze the navigation flow implementation and verification needs.

The code shows that the navigation flow has a well-designed fallback mechanism:

  1. First tries to open as a popup with specific dimensions:
window.Open(url, "_blank", new WindowFeatures() { Popup = true, Height = 768, Width = 1024 })
  1. If popup fails, tries to open in a new tab:
window.Open(url, "_blank", new WindowFeatures() { Popup = false })
  1. Finally falls back to navigating in the same tab if both previous attempts fail:
navigationManager.NavigateTo(url, forceLoad: true, replace: true)

The implementation uses the Window.Open() method from Bit.Butil which is a wrapper around the browser's window.open() API. The code shows proper handling of different scenarios with appropriate fallbacks.

Let me verify if there are any browser-specific implementations or known issues in the codebase.


Let me check the actual implementation of the window.open wrapper to verify the browser handling.


Based on the code analysis, I can now provide a final response about the navigation flow verification:

The navigation implementation is robust and browser-safe

The implementation follows best practices for cross-browser compatibility:

  1. The window.open wrapper in window.ts provides a consistent interface that:

    • Uses the native window.open() API
    • Returns a boolean indicating success/failure
    • Properly handles the windowFeatures parameter
  2. The navigation flow has proper fallbacks:

    • First attempts a popup with specific dimensions
    • Falls back to new tab if popup fails
    • Ultimate fallback to same-tab navigation
    • Each step only proceeds if the previous attempt returns false
  3. The WindowFeatures class properly formats the features string for window.open()

No browser-specific handling or known issues were found in the codebase, suggesting the implementation relies on standard web APIs that work consistently across modern browsers.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any browser-specific handling or known issues
rg -g '*.{ts,js,cs}' -i '(browser|navigator|userAgent|window\.open|popup)'

Length of output: 124470


Script:

#!/bin/bash
# Search for any browser-specific window.open implementations or overrides
ast-grep --pattern 'window.open($$$)'

Length of output: 261


Script:

#!/bin/bash
# Check the window.open implementation in window.ts
cat src/Butil/Bit.Butil/Scripts/window.ts

Length of output: 2905

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Components/ClientAppCoordinator.cs (1)

255-256: LGTM! Proper cleanup of subscription

The disposal of the PubSubService subscription is handled correctly to prevent memory leaks.

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Web/Program.Middlewares.cs (2)

60-64: Security middleware additions enhance application security

The inclusion of UseHsts, UseXContentTypeOptions, and UseXfo middleware strengthens the application's security by adding important HTTP headers.


146-146: Ensure client supports stateful reconnects with SignalR

By setting AllowStatefulReconnects to true, the server enables clients to reconnect and maintain state. Verify that the client-side code is updated to handle stateful reconnections properly to avoid unexpected behavior.

Run the following script to check for client-side SignalR configuration:

✅ Verification successful

Client code properly supports stateful reconnects with SignalR

The client-side code in Boilerplate.Client.Core already implements proper support for stateful reconnects:

  • The HubConnectionBuilder is configured with .WithStatefulReconnect() in IClientCoreServiceCollectionExtensions.cs
  • ClientAppCoordinator.cs implements proper reconnection handling:
    • Handles Reconnected, Reconnecting, and Closed events
    • Updates connection state through HubConnectionStateChange
    • Notifies the application about online status changes via PubSub
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if client code handles stateful reconnects with SignalR.

# Search for SignalR HubConnectionBuilder configurations in client-side code
rg 'HubConnectionBuilder' -g 'src/Client/**/**/*.cs' -A 5

# Check for usage of 'WithStatefulReconnect' method
rg 'WithStatefulReconnect' -g 'src/Client/**/**/*.cs' -A 2

Length of output: 414


Script:

#!/bin/bash
# Let's first find all client-side files that might contain SignalR configurations
fd -e cs -e ts -e js . src/Client

# Then search for SignalR hub configurations in all source files
rg "HubConnection" -A 5

# Also check for any SignalR-related configuration files
fd -e json . | xargs rg "SignalR"

Length of output: 9065

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Program.Middlewares.cs (2)

48-52: Security middleware additions enhance application security

The addition of UseHsts, UseXContentTypeOptions, and UseXfo middleware improves the application's security by adding essential HTTP headers.


85-85: Ensure client supports stateful reconnects with SignalR

Enabling AllowStatefulReconnects allows clients to reconnect and maintain their state. Confirm that the client application is configured to handle stateful reconnects appropriately.

Run the following script to check client-side SignalR configurations:

✅ Verification successful

Based on the search results, I can see that the client-side code in Boilerplate.Client.Core already implements stateful reconnection support through the HubConnectionBuilder configuration:

var hubConnection = new HubConnectionBuilder()
    .WithStatefulReconnect()  // Stateful reconnect is configured
    .WithUrl(new Uri(absoluteServerAddressProvider.GetAddress(), "app-hub"), options =>
    {
        options.SkipNegotiation = false;
        options.Transports = HttpTransportType.WebSockets;
    })

The client also properly handles connection state changes and reconnection events:

hubConnection.Closed += HubConnectionStateChange;
hubConnection.Reconnected += HubConnectionConnected;
hubConnection.Reconnecting += HubConnectionStateChange;

Client is already configured correctly for stateful reconnects

The client implementation properly supports stateful reconnects by using the WithStatefulReconnect() configuration and handling all relevant connection state events. No additional client-side changes are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if client code handles stateful reconnects with SignalR.

# Search for SignalR HubConnectionBuilder configurations in client-side code
rg 'HubConnectionBuilder' -g 'src/Client/**/**/*.cs' -A 5

# Check for usage of 'WithStatefulReconnect' method
rg 'WithStatefulReconnect' -g 'src/Client/**/**/*.cs' -A 2

Length of output: 414


Script:

#!/bin/bash
# Let's try a broader search for client-side SignalR configurations
# First, find all potential client files
fd -e cs -e ts -e js | grep -i "client"

# Then search for SignalR-related configurations in all files
rg "HubConnection" -A 5

# Also search for any SignalR hub usage
rg "hubConnection" -i -A 5

Length of output: 66612

src/Templates/Boilerplate/Bit.Boilerplate/src/Server/Boilerplate.Server.Api/Boilerplate.Server.Api.csproj (1)

22-22: Addition of NWebsec middleware package reference

Including the NWebsec.AspNetCore.Middleware package reference is necessary for implementing the added security middleware. Ensure this aligns with the versions specified in centralized package management.

src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages.props (1)

24-24: Added NWebsec middleware to central package management

The package version for NWebsec.AspNetCore.Middleware has been added to centralize dependency versions, ensuring consistency across projects.

src/Templates/Boilerplate/Bit.Boilerplate/src/Directory.Packages8.props (1)

24-24: Added NWebsec middleware to central package management for .NET 8

Including NWebsec.AspNetCore.Middleware in the centralized package file for .NET 8 ensures consistent dependency management across projects targeting .NET 8.

src/Templates/Boilerplate/Bit.Boilerplate/src/Client/Boilerplate.Client.Core/Extensions/IClientCoreServiceCollectionExtensions.cs (1)

Line range hint 146-171: Verify token refresh mechanism security

The token refresh implementation in the SignalR connection looks solid, but there are some security considerations to verify:

  1. The token refresh mechanism correctly validates token expiry before attempting refresh
  2. The refresh is properly attributed with requestedBy: nameof(HubConnectionBuilder)

Let's verify the token refresh implementation across the codebase:

✅ Verification successful

Token refresh mechanism is securely implemented

The verification confirms that the token refresh implementation is secure and consistent across the codebase:

  1. Token expiry validation is properly enforced before refresh:

    • The SignalR hub connection correctly validates token expiry with validateExpiry: true
    • The same validation pattern is consistently used in AuthDelegatingHandler and other components
  2. The refresh token mechanism has proper security measures:

    • Refresh tokens have a configured expiration (14 days as per appsettings.json)
    • Server-side validation in IdentityController checks both token authenticity and expiration
    • Protection against refresh token loops in AuthDelegatingHandler
    • Proper cleanup of tokens on refresh failures
  3. The requestedBy attribution is consistently used across all refresh calls for audit purposes

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other token refresh implementations to ensure consistency
rg -A 5 "RefreshToken|ParseAccessToken"

# Look for potential token validation implementations
ast-grep --pattern 'validateExpiry = true'

Length of output: 22405

@msynk msynk merged commit 239f78e into bitfoundation:develop Dec 6, 2024
3 checks passed
@ysmoradi ysmoradi deleted the 9399-external-login-through-new-tabpopup branch December 6, 2024 12:27
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.

External login through new tab/popup
2 participants